2026年、Webサービスのデファクト・スタンダードを歴史と力学から読み解く
この本が前提にしている、ひとつの変化について
数年前まで、「フルスタックエンジニア」という肩書きには、どこか胡散臭さがあった。
何でもやれる人。逆に言えば、何かに突出していない人。フロントエンドの専門家からすれば、サーバーサイドのデータベース設計やネットワーク、デプロイの細部まで本当にわかっているのか怪しいし、バックエンドの専門家からすれば、CSSやアクセシビリティをどこまで真剣にやれるのか疑わしい。両方を中途半端にやる人、というニュアンスがつきまとっていた。
ところが2026年のいま、「フルスタック」が意味するものは静かに変わってきている。
理由はシンプルだ。フロントエンドのフレームワークが、サーバーサイドの仕事を吸収してしまったからである。Next.jsのApp RouterとReact Server Componentsの組み合わせを使ったことがある人なら、もう半ば気づいているはずだ ── あなたが書いているコードは、もはやブラウザだけで動いているのではない。データベースに直接アクセスし、認証トークンを検証し、リクエストの裏でメールを送るところまで、同じファイルの中に書ける。
「フロントエンドエンジニア」と「バックエンドエンジニア」という分業を支えていた壁が、ツールチェーンのレベルで溶けはじめている。フルスタックへの越境は、もはや別世界へジャンプすることではなく、いま使っているフレームワークの、まだ触っていない機能を使い始めるだけのこと。
この記事は、フロントエンドを軸足にしてきた中堅エンジニアが、フルスタックの全景を一度見渡すための地図である。技術カタログではない。むしろ逆で、「なぜいまこの構成が標準になっているのか」を歴史と力学から辿り直し、自分が次にどこへ足を伸ばすかを判断できるようにすることを狙っている。
かつての「フロント/バック」の役割分担は、フレームワークのレベルで境界が溶けてきている。
通読には30分ほどかかる。コーヒーを淹れて、はじめよう。
流行り廃りに見えるものの多くは、ひとつの振り子運動として説明がつく
いまのWebの設計を理解するうえで、いちばん効率のいい近道は、「Webアプリの処理は、過去20年でサーバーとクライアントのあいだを大きく振り子のように揺れ動いてきた」という事実から出発することだ。流行り廃りに見えるものの多くは、この振り子の運動として説明がつく。
最初期のWebは、純粋なサーバーレンダリングだった。PHPでもPerlでも、Ruby on RailsでもDjangoでもいい。ブラウザがリクエストを送る、サーバーがHTMLを返す、ユーザーがリンクをクリックする、また新しいHTMLが返ってくる。これだけだ。JavaScriptはあくまでフォーム検証やちょっとしたアニメーションのためのスパイスにすぎなかった。
このモデルは美しいほど単純だった。状態はサーバー側にしかなく、画面遷移はページ全体の再読み込みで起きる。バグの再現も簡単で、SEOも勝手にうまくいく。
問題は、ユーザー体験の地味さだった。クリックするたびに白い画面が一瞬挟まる。動的な操作をやろうとすると、ページ全体を再生成するしかない。これではデスクトップアプリのような滑らかさは出せない。
2010年代に入ると、ブラウザの性能が上がり、JavaScriptで本格的にアプリケーションを書くことが現実的になった。AngularJSが先陣を切り、Backbone、Ember、そして決定打となったReact。これらが切り開いたのが、Single Page Application(SPA)というパラダイムだ。
考え方は鮮やかだった。最初に空のHTMLとJavaScriptのバンドルを送り、あとはブラウザ側で全部やる。画面遷移はURLを書き換えてDOMを差し替えるだけ。サーバーは、状態を持たないAPIサーバーとしてJSONを返すだけの存在になる。
これは衝撃的な進歩で、いっとき業界全体がSPAに向かって走った。フロントエンドという職種が独立した専門領域として確立したのも、この時期だ。バックエンドが「データを返すだけ」になったことで、フロントエンドが「アプリケーションの全部」を担うようになった。
ところが、振り子は行きすぎた。
数年もしないうちに、SPA一辺倒の弊害が見えてきた。
第一に、初期表示の遅さ。空のHTMLを受け取ったあと、巨大なJavaScriptバンドルをダウンロードし、パースし、実行し、それからやっとデータをフェッチしに行く。最初の画面が出るまで何秒もかかるサイトが量産された。
第二に、SEOの困難さ。検索エンジンのクローラーはJavaScript実行が苦手なため、コンテンツが空のままインデックスされる問題が起きた。これはECサイトやメディアサイトには致命的だった。
第三に、状態管理の地獄。サーバーが全部やっていた頃は意識しなくてよかった「データの取得・キャッシュ・無効化」のすべてが、クライアントに乗ってきた。Reduxの登場と、それに伴うボイラープレートの肥大化を覚えている人も多いだろう。
第四に、バンドルサイズの肥大化。アプリが成長するほどJavaScriptが膨らみ、モバイルユーザーが特に苦しんだ。
これらは小さなプロジェクトなら無視できる問題だった。しかし、「ちゃんとしたWebサービス」を作ろうとすると必ず突き当たる壁になった。
2010年代後半、ひとつの折衷案が広まる。Jamstackと呼ばれる発想だ。ビルド時に静的HTMLを大量生成し、CDNから配信する。動的な部分だけJavaScriptで補う。Gatsby、Next.jsの初期(SSG中心)、Hugo、Eleventyなどがこの潮流の代表だ。
これは賢い解決策だった。事前にHTMLを生成しておけば初期表示は速いし、SEOも問題ない。ただし、本当に動的なコンテンツ ── ユーザーごとに異なる情報、リアルタイムに更新される情報 ── を扱うのは苦手だった。
2020年代に入って、流れは決定的に変わった。
Next.jsはSSR(Server-Side Rendering)を中心に据え直し、Vercelをはじめとするインフラはサーバー実行を当たり前のものにした。そして2023年にReact Server Components(RSC)がNext.js App Routerで実用段階に入ると、振り子は完全にサーバー側へ戻りはじめた。
RSCの発想はこうだ。「データベースアクセスや重い処理は、もともとサーバーでやればよかった。クライアントに送る必要があるのは、ユーザーの操作に反応する部分だけだ」。コンポーネントごとに、どこで実行するかを宣言できるようになった。サーバーで動くコンポーネントはJavaScriptバンドルに含まれない。
なにが起きたか。バンドルサイズは劇的に小さくなり、初期表示は速くなり、データ取得は素直に書けるようになった。クライアントには、本当にインタラクティブな部分だけが残った。
処理がサーバー側にあるか、クライアント側にあるか。Webアプリの設計はこの軸を振り子のように行き来してきた ── 同じ場所には戻らない、らせん状の進化として。
ここで重要なのは、いまのサーバー回帰が「昔に戻った」のではないという点だ。私たちは、サーバーレンダリングの素朴さと、SPAのリッチさを、ようやく統合する道を見つけはじめている。コンポーネント単位でサーバーとクライアントの境界を引けるという発想は、過去の二択ではどちらにも到達できなかった地点だ。
振り子は揺れているが、揺れるたびに少しずつ前に進んでいる。
2026年のWebサービス開発を理解するには、「処理はサーバーとクライアントのどちらに置くべきか」という問いが、いまや設計の中心にあることを認識すること。これがすべての出発点になる。
なぜ素のReactで作る人がいなくなったのか
振り子の歴史を踏まえたうえで、次の問いに進もう。なぜ2026年のいま、誰もが Next.js のようなメタフレームワークから始めるのか。素のReactで作る人を、もう見かけないのはなぜか。
少し時間を巻き戻す。SPAが全盛だった頃、Reactでアプリを作るとは、概ねこういうことだった。
まずCreate React Appか、もう少し凝るならwebpackを自分で設定する。ルーティングはReact Routerを入れる。データフェッチはfetchをそのまま使うか、ReduxにThunkかSagaを足す。スタイリングはCSS ModulesかStyled Components。フォームは react-hook-form か Formik。テストはJestとReact Testing Library。デプロイはAWSのS3にビルド成果物を上げて、CloudFrontで配信する。
それぞれの選択に正解はなく、チームごと、プロジェクトごとに微妙に違うスタックが組まれていた。コミュニティで議論が絶えなかった ── どのルーターが最良か、どの状態管理が最良か、どのスタイリングが最良か。
これは「自由」だった。しかし、その自由には代償があった。
新しいプロジェクトを始めるたびに、技術選定の長い会議が必要だった。新しくチームに入った人は、その会社独自のスタック構成を理解するのに数週間かかった。webpack の設定地獄、Babel のプラグイン地獄、TypeScript の tsconfig.json 調整 ── 本来やりたいプロダクト開発に入る前の「セットアップ」に、信じられないほどの時間が吸われていた。
しかも、各部品の選択は独立していなかった。ルーターをこれにすると、データフェッチはこれと相性が悪い、SSRするにはこの設定が必要、デプロイ先によっては動かない、といった組み合わせ問題が無限に発生した。
Next.js が広めたのは、「これらを全部、一つのフレームワークが面倒を見る」という発想だ。
ルーティング、データフェッチ、レンダリング戦略(SSR、SSG、ISR、CSR)、画像最適化、フォント最適化、APIエンドポイント、ミドルウェア、認証フロー、デプロイ最適化 ── 個別に選んでいたものを、すべてフレームワークが一貫した思想で提供する。
これは思想の転換だった。「ライブラリを組み合わせる」のではなく、「フレームワークの上で書く」。後者はかつてのRuby on RailsやLaravelが標榜してきた「Convention over Configuration(設定より規約)」の思想そのものだ。意外なことに、Webフロントエンドの世界は20年遅れて同じ答えにたどり着いた。
そしてApp RouterとReact Server Componentsが加わったことで、Next.jsは「フロントエンドフレームワーク」を完全に超えた。サーバーで動く処理、データベース直結のコンポーネント、フォーム送信を受け取るServer Actions ── これらはすべて、かつてバックエンドのPHPやRailsが担っていた領域だ。
技術選定の自由は、その代償も大きかった。メタフレームワークは、それらを一つの思想で統合する。
Next.js だけがメタフレームワークではない。それぞれが少しずつ違う思想で、しかし共通の方向を向いている。
| フレームワーク | ベース | 立ち位置 |
|---|---|---|
| Next.js | React | デファクト。フルスタックの第一選択 |
| Nuxt | Vue | Vue陣営の標準。Next.jsと思想は近い |
| SvelteKit | Svelte | より軽量、より「Webらしい」 |
| Remix | React | データローディングとWeb標準への忠実さに特化 |
| Astro | 何でも | コンテンツ中心サイト向け。Islands Architecture |
| TanStack Start | React | 型安全とDXに極振り、新興 |
| Qwik | 独自 | Resumability。ハイドレーション不要を志向 |
それぞれ強みは違うが、共通しているのは「ルーティング・データフェッチ・サーバー処理・ビルド・デプロイまで一気通貫」という設計思想だ。
この章の主題は、フロントエンドエンジニアにとっての朗報だ。
あなたがNext.jsでアプリを書いているなら、もうあなたは「サーバーサイドの世界」に半分足を踏み入れている。Server Componentでデータベースに直接クエリを書く。Server Actionでフォーム送信を受ける。これらは数年前なら「バックエンドエンジニアの仕事」だった領域だ。
つまり、「フロントエンドからフルスタックへの越境」は、もはや別世界へジャンプすることではない。いま使っているフレームワークの、まだ触っていない機能を使い始めるだけのことだ。心理的なハードルが、こんなにも低くなった時代はかつてなかった。
ただし、フレームワークが面倒を見てくれる範囲には限界がある。データベース設計の良し悪し、認証の安全な実装、本番環境での障害対応 ── このあたりはフレームワークが助けてくれない。第4章以降で、それらを順に見ていく。
未知の領域に降りていく前に、足場を確認する
第4章でバックエンドの世界に降りていく前に、現在のフロントエンドの「標準的な構成」を一度確認しておく。読者であるあなたにはほぼ既知の内容のはずなので、ここは答え合わせとアップデートのつもりで読んでほしい。
2026年のプロのプロジェクトで素のJavaScriptを書くことは、ほぼ「レガシー」と同義になった。新規プロジェクトはTypeScriptで始める。strictモード推奨。これは議論の余地がない。
なぜか。クライアントとサーバーの境界が溶けたいま、両者で型を共有することの利益が桁違いになったからだ。Server ComponentがDBから取ってきたデータをClient Componentにpropsで渡す。tRPCやServer Functionでクライアントからサーバー関数を呼ぶ。これらが型安全に貫通することの開発体験は、一度味わうと戻れない。
Tailwind CSSがフロントエンドのスタイリングを実質的に制圧した。CSS-in-JS陣営(styled-components, Emotion)はランタイムオーバーヘッドとサーバーコンポーネントとの相性問題で勢いを失い、CSS Modules派は静かに残っているが、新規プロジェクトの第一選択はほぼTailwindだ。
そこに、新しい配布形態を持ち込んだのが shadcn/ui である。これは「ライブラリではない」。npmからインストールするのではなく、CLIでコードを自分のリポジトリにコピーして、自分で所有して書き換える。Radix UI(ヘッドレスUI)とTailwindの組み合わせのレシピ集だと思えばいい。
この「npmで配らない、ソースコードを所有させる」というアプローチは思想的に新しく、UIライブラリの未来を変えつつある。バージョンアップに振り回されず、必要な改変が自由にでき、依存関係が増えない。
かつてはReduxが何でも管理していた。いまは違う。
サーバー状態には独自のライフサイクルがある ── フェッチ、キャッシュ、再検証、楽観的更新、エラー処理。これらをまとめて面倒を見てくれるのがTanStack Queryで、これは Redux Saga やThunkで書いていた処理の大半を不要にする。
クライアント状態(モーダルの開閉、フォームの一時値、UIのトグル)はZustandやJotaiのような軽量ライブラリで十分。Reduxの大規模なボイラープレートを正当化できるケースは、もうほとんどない。
そしてフォーム状態は React Hook Form + Zod(バリデーション)の組み合わせがほぼ標準になっている。
Reduxが全てを抱え込んでいた時代は終わった。サーバーから来るデータと、UIの一時的な状態は、別の道具で扱う。
長らくReact開発者を悩ませてきた「useMemoとuseCallbackをどこまで貼るか問題」は、React Compilerによって過去のものになりつつある。コンパイル時に依存関係を解析し、必要なメモ化を自動で挿入する。
これは設計思想にも影響を与える。「パフォーマンスのために汚いコードを書く」ことが減り、「読みやすく書いて、最適化はコンパイラに任せる」という方向に進む。フロントエンドが、ようやく他の言語のコンパイラの恩恵を享受しはじめている。
プロジェクトが大きくなったとき、どうフォルダを切るか。これは長らく各社各様だったが、いくつかの収束が見える。
ひとつは Colocation。コンポーネント、そのテスト、スタイル、フックを同じフォルダにまとめる。Button/Button.tsx、Button/Button.test.tsx、Button/index.tsという形だ。「機能ごとにファイルがバラバラのフォルダにある」よりも、「関連するものは近くに置く」ほうが認知負荷が低い。
もうひとつは、より大きな単位での Feature-Sliced Design(FSD)的な構成。features/、entities/、widgets/、shared/ といったレイヤーで責務を分けるアプローチで、特に大規模プロジェクトで採用が増えている。中小規模ならここまで厳密にしなくても、src/features/{機能名}/に閉じ込めるだけでも効果は大きい。
「コンポーネント単位」だけでは構造化が足りない、というのが大規模アプリの教訓だった。ビジネスロジックや機能の単位で、横断的に括れる構造を持つこと ── これは2026年のフロントエンドの新常識として定着した。
境界線は、ファイルの場所では決まらない
ここからが本題だ。
フロントエンドエンジニアがフルスタックを目指すとき、最初に戸惑うのは「バックエンドとは結局なんなのか」がぼんやりしていることだ。ReactのServer Componentでデータベースに繋ぐコードを書いたとき、それはバックエンドなのか、それともまだフロントエンドなのか。答えを先に言ってしまうと ── 境界線は、もはやファイルの場所では決まらない。実行環境とライフサイクルで決まる。
歴史を巻き戻して整理しよう。バックエンドの世界は長らく、PHP、Java、Python、Ruby、C#、Goといった「フロントエンドとは別の言語」で書かれてきた。フロントエンドエンジニアが越境しようとすると、まず言語を覚え直すところから始める必要があった。これは大きな心理的ハードルだった。
Node.jsの登場(2009年)が、この壁を最初に壊した。JavaScriptで書けるバックエンド。当初は懐疑的な目で見られたが、いまや本流の一つだ。そしてTypeScriptの普及によって、Node.jsはエンタープライズ用途でも信頼に足る選択肢になった。
つまり、いまフロントエンドエンジニアがバックエンドに踏み込むとき、言語の壁は基本的にない。これは2010年代には考えられなかった幸運だ。Next.jsのServer Componentsで書いているコードは、すでにNode.js上で動くサーバーサイドコードである。
ただし、現実のWebサービス開発では、Node.js一択にならない場面もある。用途別に簡単に整理しておく。
| 言語 | 代表フレームワーク | こういう時に選ばれる |
|---|---|---|
| TypeScript (Node.js) | Next.js, Hono, Elysia, NestJS | フロントと統一、フルスタック型安全 |
| Go | 標準ライブラリ、Echo、Gin | 高並行・低レイテンシ・シンプル |
| Python | FastAPI、Django | AI/ML統合、データ処理 |
| Ruby | Rails | 高速プロトタイピング、スタートアップ |
| Java/Kotlin | Spring Boot | 大規模エンタープライズ、堅牢性重視 |
| PHP | Laravel | 既存PHP資産、共有ホスティング |
| Rust | Axum | 高性能・メモリ安全が必須、システム寄り |
フロントエンドエンジニアがフルスタック化するとき、最初はTypeScriptで統一するのが圧倒的に楽だ。同じ言語、同じパッケージマネージャ、同じ型システム。学習コストが最小化される。
GoやPythonに踏み出すのは、特定の理由(性能、AI連携、既存資産)があるときでいい。「バックエンド = TypeScript以外の言語」という思い込みは捨てていい。
ここで、ひとつ重要な概念を紹介する。BFF(Backend for Frontend) だ。
BFFというのは、「フロントエンドのために専用に作られたバックエンド」のことだ。汎用的なAPI(マイクロサービス的なもの)とは別に、特定のフロントエンドアプリケーション(Webサイト、モバイルアプリ)のために設計されたサーバーを置く。データの集約、認証、画面ごとに必要な情報の整形などをやる。
なぜこんなものが必要になったか。クライアントから複数のマイクロサービスを直接叩くのは、ネットワーク的に非効率だし、認証情報の管理も面倒だ。間に「自分専用のサーバー」を一枚挟むほうが、全部きれいに収まる。
Next.jsのApp Router + Server Componentsで書いているコードは、実質的にBFFそのものだ。あなたはすでに、フロントエンドのためのバックエンドを書いている。「バックエンドへの越境」は、もう始まっている。
数年前まで、バックエンドの主な仕事は「REST APIを設計し、実装すること」だった。エンドポイントを切り、リクエスト・レスポンスのスキーマを決め、ドキュメントを書き、クライアントから呼ぶ。
この作業を不要にしたのが、Server Actions と tRPC だ。
Server Actions はReactとNext.jsの機能で、サーバーで動く関数を、まるでクライアントの関数のように呼べる。'use server' ディレクティブをつけた関数は、フレームワークが裏でHTTP通信に変換してくれる。フォームの送信先に直接Server Actionを指定することもできる。
// app/actions.ts
'use server';
export async function createPost(formData: FormData) {
const title = formData.get('title') as string;
await db.posts.create({ title });
}
// app/page.tsx
import { createPost } from './actions';
export default function Page() {
return (
<form action={createPost}>
<input name="title" />
<button type="submit">作成</button>
</form>
);
}
「APIエンドポイントを切る」「fetchで呼ぶ」「レスポンスを処理する」 ── これらの作業がまるごと消える。これがフロントから見たときの衝撃だ。
tRPC は別系統だが、思想は近い。サーバー側で定義した関数を、クライアントから型安全に呼び出せる。OpenAPIスキーマを書かなくても、TypeScriptの型がそのまま通信を貫通する。
これらの仕組みが、「フロントエンドとバックエンドのあいだの面倒な接続作業」を消し去った。フロント中心のエンジニアにとっては福音だ。
「サーバー関数を、まるでクライアントの関数のように呼べる」 ── これがフロント開発者がフルスタックに近づく最大の梯子。
ただし、REST API(あるいはOpenAPIに準拠したAPI)が消えたわけではない。むしろ、用途が明確になっただけだ。
REST APIが今でも必要なのは、こういう場面だ。
つまり、「同じチームが書くWebアプリ内部」では Server Actions / tRPC で済むが、「外と通信する」場合はやはりRESTが必要、という棲み分けだ。OpenAPI仕様を書くことは、いまも基本スキルとして必要である。
ついでに、GraphQLについても触れておく。2015年にFacebookが発表してから一気に流行ったが、2026年現在、勢いは落ち着いている。
GraphQLが本当に活きるのは、「クライアントが取得したいデータを柔軟に指定したい」場面 ── たとえば、複雑なダッシュボードや、複数のフロントエンドが同じAPIを共有する場面だ。GitHubやShopifyのような巨大プラットフォームでは今も中心的な技術である。
一方、シンプルなWebアプリで導入するには、サーバー側の実装が重く、N+1問題などのパフォーマンス管理が難しい。Server Actions / tRPC のほうが軽量で、多くのケースで十分という認識になった。