少し前まで、ReactベースでWebアプリを作るなら
「とりあえずNext.js」という空気がありました。
しかし最近は、
-
バンドルが重くなりがち
-
抽象化が多くて内部が見えにくい
-
もっと軽量な選択肢があるのでは?
といった声も増えています。
実際、Vercel が開発する Next.js 以外にも、
Astro、SvelteKit、Qwik などが実運用レベルで普及し、
選択肢は明確に広がりました。
とはいえ、「批判されている=劣っている」という話ではありません。
重要なのは、思想の違いがどのようなコードと配信物(HTML/JS)の違いを生むのかです。
現在の大きな潮流は、
-
Hydration を減らす(あるいは回避する)
-
配信する JS を必要箇所に限定する
-
サーバー実行を増やす
という Ship less JavaScript の方向に集約されつつあります。
今回は、以下4つのフレームワークの設計思想を比較します。
- Next.js
- Astro
- SvelteKit
- Qwik
コード比較する機能
まずは最も単純な例として「カウンター」を実装します。
仕様
-
初期値 0
-
ボタンを押すと +1
このシンプルな機能でも、各フレームワークの思想が見えてきました。
1. Next.js(Server Components + Client Components)
Next.js の App Router では Server Components がデフォルトです。
インタラクティブな部分だけを Client Component に分離します。
// Server Component
import CounterClient from "./CounterClient";
export default function Page() {
return (
<div>
<h1>Counter</h1>
<CounterClient />
</div>
);
}
// Client Component
"use client";
import { useState } from "react";
export default function CounterClient() {
const [count, setCount] = useState(0);
return (
<div>
<p>{count}</p>
<button onClick={() => setCount((c) => c + 1)}>
Increment
</button>
</div>
);
}
特徴
-
Reactベース
-
"use client"を付けたコンポーネントのみがクライアントJSになる -
それ以外はサーバーでHTML生成
思想
Next.js は
「サーバー中心にし、必要な部分だけをクライアント化する」
という方向へ進化しています。
2. Astro(Islands Architecture)
Astro は HTMLを基本とし、
インタラクティブな部分だけを「アイランド」として読み込みます。
---
import Counter from "../components/Counter.tsx";
---
<Counter client:load />
import { useState } from "react";
export default function Counter() {
const [count, setCount] = useState(0);
return (
<>
<p>{count}</p>
<button onClick={() => setCount((c) => c + 1)}>
Increment
</button>
</>
);
}
特徴
-
デフォルトはHTMLのみ
-
client:*を付けた部分だけJS化 -
読み込みタイミングも制御可能
思想
HTMLを出し、JSは必要な分だけ後から足す という考え方。
3. SvelteKit
SvelteKit は SSR → hydration がデフォルトです。
<script>
let count = 0;
</script>
<p>{count}</p>
<button on:click={() => count += 1}>
Increment
</button>
特徴
-
状態管理が非常にシンプル
-
コンパイル時に最適化
-
csr=false でクライアントJSを無効化可能
思想
SSRを前提にしつつ、軽量なJSを生成する という考え方。
4. Qwik
Qwik は hydrateせずに resume する設計です。
import { component$, useSignal } from "@builder.io/qwik";
export default component$(() => {
const count = useSignal(0);
return (
<div>
<p>{count.value}</p>
<button onClick$={() => count.value++}>
Increment
</button>
</div>
);
});
特徴
-
useSignalによる細粒度状態管理 -
$境界は遅延ロード可能 -
実装コードは必要になるまで読み込まれない
思想
Resumability(再開可能性)
= ページの状態をそのまま復元する という考え方。
実装から見える思想の違い
| フレームワーク | デフォルトの前提 | インタラクティブ化単位 |
|---|---|---|
| Next.js | Server Components |
"use client" 境界 |
| Astro | HTML + Islands |
client:* 指定 |
| SvelteKit | SSR → hydration | ページ / コンポーネント |
| Qwik | Resume |
$ 境界 |
実務的な選定指針
コンテンツ中心サイト
→ Astro
SSR前提で軽量なUI
→ SvelteKit
極限まで初期JSを削りたい
→ Qwik
エコシステム重視・企業開発
→ Next.js
結論
Next.js 一強の時代は、終わったというより「多様化した」 と言えます。
重要なのは、
「どれが最強か」ではなく、
「どれが要件に合うか」
フレームワークは目的ではなく手段。
コードの違いは、思想の違いです。
参考
-
Next.js
https://nextjs.org/docs -
SvelteKit
https://kit.svelte.dev/docs
採用拡大中!
アシストエンジニアリングでは一緒に働くフロントエンド、バックエンドのエンジニアを募集しています!
少しでも興味ある方は、カジュアル面談からでもぜひお気軽にお話ししましょう!
お問い合わせはこちらから↓
https://official.assisteng.co.jp/contact/