Nuxtのレンダリング方式は、nuxt.config.ts の routeRules で「ページ(URL)ごと」に選べます。 トップページはビルド時に静的HTMLにし(SSG)、記事一覧は数秒〜数分キャッシュし(SWR・ISR)、管理画面はブラウザだけで描画する(SPA)、といった組み合わせを1つのアプリで実現できます。これを ハイブリッドレンダリング と呼びます。

この記事では、Nuxt 4.5.2(Nitro 2.13.4) で、各方式の違いと選び方を表にまとめ、routeRules の 全オプションを型定義から確認した早見表 とコピペ用の設定を載せます。さらに、実際に nuxt build / nuxt generate を実行した出力、curl -I で取得した各ルートの cache-control などのヘッダー、SWRで表示時刻が更新される間隔の実測ログ、Vercel・Netlify向けにビルドしたときのISR設定ファイルまで、実行結果つきで確認します。

Nuxtのレンダリング方式 早見表

方式 routeRules の書き方 HTMLを作るタイミング キャッシュ 向いているページ
SSR(サーバーサイドレンダリング) 指定なし(既定) リクエストのたび なし 会員ごとに内容が変わるページ、在庫など常に最新が必要なページ
SPA(クライアント描画) { ssr: false } ブラウザでJSが実行されたとき なし 管理画面、ログイン後のダッシュボード
SSG(事前レンダリング) { prerender: true } nuxt build のとき 静的ファイル トップ、会社概要、規約など更新が少ないページ
SWR { swr: 秒数 } 初回アクセス時+期限切れ後に裏で再生成 Nitroのサーバー内キャッシュ+s-maxage 記事一覧、ランキングなど数秒〜数分の遅れを許せるページ
ISR { isr: 秒数 } 初回アクセス時+期限切れ後に再生成 対応ホスティングのCDN Vercel・Netlifyでの記事ページ、商品ページ
cache { cache: { maxAge: 秒数 } } 期限切れ後の最初のリクエストで作り直す Nitroのサーバー内キャッシュ+max-age 古い版を返したくないが、短時間はキャッシュしたいページ
  • 迷ったら「既定はSSR、更新が少ないページだけ prerender: true」から始めるのが安全です。
  • SWRとISRの違いは「どこにキャッシュするか」。SWRはNitroサーバー、ISRはホスティングのCDNです。Node.jsサーバーで動かす場合、isr はキャッシュされず SSRと同じ動き になりました(後述の実測)。
  • nuxt generate で全ページを静的化すると、ハイブリッドレンダリング(SWR・ISR・SSR)は使えません(公式ドキュメントに明記)。

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「Nuxt SSR・SSGの設定|routeRules全オプションとヘッダー実測」

検証環境

項目 バージョン
Nuxt 4.5.2
Nitro 2.13.4(preset: node-server)
Vue / Vite 3.5.43 / 8.3.1
Node.js 22.22.2(Nuxt 4.5 は ^22.19 以上が必要)

プロジェクトは npm install nuxt@4.5.2 で作った最小構成です。各ページで /api/now(現在時刻を返すAPI)を useFetch し、HTMLに埋め込まれた時刻=そのHTMLが作られた時刻 として観察しました。

// server/api/now.get.ts
export default defineEventHandler(() => ({ now: new Date().toISOString() }))
<!-- app/pages/swr.vue(ssr.vue・isr.vue なども同じ中身) -->
<script setup lang="ts">
const { data } = await useFetch('/api/now', { key: 'swr' })
</script>
<template>
  <main>
    <h1>swr</h1>
    <p id="rendered">{{ data?.now }}</p>
  </main>
</template>

どの方式を選ぶか(判断表)

判断の軸は「内容が人によって変わるか」「どれくらい古くてもよいか」「どこにデプロイするか」の3つです。

flowchart TD
  A[そのページはログインした人ごとに内容が変わる?] -->|はい| B{検索エンジンに載せる?}
  B -->|いいえ| SPA["ssr: false(SPA)"]
  B -->|はい| SSR["指定なし(SSR)"]
  A -->|いいえ| C{内容はビルドのときに決まる?}
  C -->|はい| SSG["prerender: true(SSG)"]
  C -->|いいえ| D{数秒〜数分古くてもよい?}
  D -->|いいえ| SSR
  D -->|はい| E{Vercel / Netlify にデプロイ?}
  E -->|はい| ISR["isr: 秒数"]
  E -->|いいえ| SWR["swr: 秒数"]
状況 おすすめ 理由
会社概要・規約・LP prerender: true サーバー処理ゼロ。CDNからそのまま配信できる
ブログ記事(Node.jsで運用) swr: 600 など 初回以降はキャッシュから即返し、裏で最新化
ブログ記事(Vercel / Netlify) isr: 600 など CDNにキャッシュされ、関数の起動回数も減る
在庫数・予約枠など常に最新 指定なし(SSR) キャッシュすると古い数字が表示される
管理画面 ssr: false 検索エンジン向けのHTMLが不要。サーバー負荷も減る
数秒だけキャッシュし、古い版は返したくない cache: { maxAge: 5, swr: false } 期限切れ時は作り直してから返す

routeRules の全オプション早見表

Nuxt 4.5.2 で使える routeRules のキーを、Nitroの型定義(NitroRouteConfig)とNuxtの型拡張から確認した一覧です。

オプション 型 役割 例
prerender boolean ビルド時に静的HTMLを作る '/': { prerender: true }
ssr boolean false でサーバー描画をやめ、SPAにする '/admin/**': { ssr: false }
swr boolean | number Nitroでキャッシュし、期限後は古い版を返しつつ再生成 '/news': { swr: 60 }
isr boolean | number | object 対応ホスティングのCDNでキャッシュ(true は期限なし) '/blog/**': { isr: 3600 }
cache object | false Nitroのキャッシュを細かく指定(maxAge、swr、staleMaxAge、varies など) { cache: { maxAge: 5, swr: false } }
headers Record<string, string> レスポンスヘッダーを追加 { headers: { 'x-robots-tag': 'noindex' } }
redirect string | { to, statusCode } リダイレクト(文字列だけなら 307) { redirect: { to: '/new', statusCode: 301 } }
cors boolean CORSヘッダー4つを自動追加 '/api/**': { cors: true }
proxy string | { to, ...} 別のURLへ転送 '/proxy/**': { proxy: 'https://example.com/**' }
noScripts boolean NuxtのJSとリソースヒントを出力しない '/lite': { noScripts: true }
appMiddleware string | string[] | Record<string, boolean> Vue側のルートミドルウェアを実行する/しない { appMiddleware: { auth: false } }
appLayout string | false レイアウトをまとめて指定(Nuxt 4.3以降) '/admin/**': { appLayout: 'admin' }
static boolean | number 旧来のオプション(Vercel向けの互換用)。新規は isr を使う —
  • パスは /** で配下すべて、/* で1階層だけにマッチします。
  • streaming というキーも型定義にはありますが、公式ドキュメントのRoute Rules一覧には載っていないため、この記事では扱いません。
  • experimentalNoScripts は非推奨になり、noScripts に置き換わっています(型定義の @deprecated 表記で確認)。

コピペで使える nuxt.config.ts(ハイブリッドレンダリング)

以下が、この記事の実測に使った設定です。そのまま貼って、パスを自分のサイトに合わせて書き換えれば動きます。

// nuxt.config.ts(Nuxt 4.5.2)
export default defineNuxtConfig({
  compatibilityDate: '2026-09-01',
  devtools: { enabled: false },
  routeRules: {
    // SSG:ビルド時にHTMLを作る
    '/': { prerender: true },
    // SPA:サーバーではHTMLの中身を作らない
    '/spa': { ssr: false },
    // SWR:10秒キャッシュ、期限切れ後は古い版を返しつつ裏で作り直す
    '/swr': { swr: 10 },
    // ISR:対応ホスティング(Vercel/Netlify)ではCDNにキャッシュ
    '/isr': { isr: 60 },
    // cache:Nitroのキャッシュを細かく指定
    '/cached': { cache: { maxAge: 5, swr: false } },
    // ヘッダーを追加
    '/lite': { noScripts: true, headers: { 'x-robots-tag': 'noindex' } },
    // リダイレクト(既定は307)
    '/old-page': { redirect: '/' },
    '/moved': { redirect: { to: '/ssr', statusCode: 301 } },
    // API:CORSとキャッシュ無効
    '/api/**': { cors: true, headers: { 'cache-control': 'no-store' } },
    // プロキシ(ここでは同じサーバーのAPIへ転送)
    '/proxy/**': { proxy: '/api/**' },
    // 管理画面:SPAにして、レイアウトもまとめて指定
    '/admin/**': { ssr: false, appLayout: 'admin' },
  },
})

ルールは複数のパターンに当てはまると合成されます。 たとえば '/blog/**': { isr: 3600 } と '/blog/draft/**': { ssr: false } を両方書くと、/blog/draft/1 には両方が適用されます。意図しない組み合わせを避けるには、パターンを重ねすぎないのがコツです。

nuxt build の実行結果:prerender されたファイル

npx nuxt build を実行すると、prerender: true のページだけがビルド中にHTML化されます。

•  Nuxt 4.5.2 (with Nitro 2.13.4, Vite 8.3.1 and Vue 3.5.43)
•  Nitro preset: node-server
[nitro] i Initializing prerenderer
[nitro] i Prerendering 1 routes
[nitro]   ├─ / (90ms)
[nitro]   ├─ /_payload.json (6ms)
[nitro] i Prerendered 2 routes in 1.657 seconds
[nitro] √ Generated public .output/public
[nitro] i Building Nuxt Nitro server (preset: node-server, compatibility date: 2026-09-01)
[nitro] √ Nuxt Nitro server built
[nitro] √ You can preview this build using node .output/server/index.mjs

出力された静的ファイル(_nuxt/ 配下のJS・CSSを除く)は次の2つでした。

.output/public/_payload.json
.output/public/index.html

_payload.json は、useFetch で取得したデータの保存ファイルです。別のページから NuxtLink で移動してきたとき、APIを呼び直さずにこのファイルを読みます。

ビルド中のリクエストには x-nitro-prerender ヘッダーが付く

prerender はNitroが自分自身にリクエストを送って行います。サーバーミドルウェアでヘッダーを記録すると、ビルド中だけ x-nitro-prerender リクエストヘッダーが付くことが確認できました。

// server/middleware/prerender-log.ts(確認用)
export default defineEventHandler((event) => {
  const h = getRequestHeader(event, 'x-nitro-prerender')
  if (h) console.log('[prerender]', event.path, 'x-nitro-prerender =', h)
})
[prerender] / x-nitro-prerender = /
[prerender] /api/now x-nitro-prerender = /
[nitro]   ├─ / (366ms)
[prerender] /_payload.json x-nitro-prerender = /_payload.json
[nitro]   ├─ /_payload.json (4ms)

ページの中で呼んだ /api/now にも同じヘッダーが付いています。 ビルド時だけ処理を変えたい(外部APIの呼び出しを減らすなど)ときの判定に使えます。なお、配信時のレスポンスにはこのヘッダーは付きません。

prerender の対象を増やす方法

方法 書き方 使いどころ
routeRules '/about': { prerender: true } パスが決まっているページ
nitro.prerender.routes nitro: { prerender: { routes: ['/items/1', '/items/2'] } } 動的ルートのURLを列挙する
nitro.prerender.crawlLinks nitro: { prerender: { crawlLinks: true } } prerenderしたページのリンクをたどって追加
nitro.prerender.ignore nitro: { prerender: { ignore: ['/dynamic'] } } 対象から外す
prerenderRoutes() ページ内で prerenderRoutes(['/items/3']) 取得したデータからURLを追加する

curl -I で各ルートのヘッダーを実測

PORT=7450 node .output/server/index.mjs で起動し、各ルートに curl -I を送った結果です(date・connection などの共通ヘッダーは省略)。

パス ルール ステータス 主なヘッダー
/ prerender: true 200 ETag、Last-Modified(静的ファイルとして配信。x-powered-by なし)
/ssr なし 200 x-powered-by: Nuxt のみ。cache-control なし
/spa ssr: false 200 x-powered-by: Nuxt のみ
/swr swr: 10 200 cache-control: s-maxage=10, stale-while-revalidate、etag、last-modified
/isr isr: 60 200 x-powered-by: Nuxt のみ(Node.jsでは cache-control なし)
/cached cache: { maxAge: 5, swr: false } 200 cache-control: max-age=5、etag、last-modified
/lite noScripts + headers 200 x-robots-tag: noindex
/old-page redirect: '/' 307 location: /
/moved redirect: { statusCode: 301 } 301 location: /ssr
/api/now cors + headers 200 access-control-allow-* 3つ、access-control-max-age: 0、cache-control: no-store
/proxy/now proxy: '/api/**' 200 転送先 /api/now と同じJSONとヘッダー

実際の出力(抜粋)です。

=== /
HTTP/1.1 200 OK
Content-Type: text/html;charset=utf-8
ETag: "726-OrRtedBa7phdcp28EM4mrkFL404"
Last-Modified: Tue, 29 Sep 2026 10:24:19 GMT

=== /swr
HTTP/1.1 200 OK
last-modified: Tue, 29 Sep 2026 10:24:33 GMT
etag: W/"oe1yqmxzb0"
cache-control: s-maxage=10, stale-while-revalidate
content-type: text/html;charset=utf-8
x-powered-by: Nuxt

=== /cached
HTTP/1.1 200 OK
last-modified: Tue, 29 Sep 2026 10:24:33 GMT
etag: W/"SAkkEpjCUQ"
cache-control: max-age=5
content-type: text/html;charset=utf-8
x-powered-by: Nuxt

=== /old-page
HTTP/1.1 307 Temporary Redirect
location: /
content-type: text/html

=== /moved
HTTP/1.1 301 Moved Permanently
location: /ssr
content-type: text/html

swr は s-maxage(CDN・共有キャッシュ向け)、cache は max-age(ブラウザも含む) が付く点が違います。max-age はブラウザ自身もキャッシュするため、更新をすぐ見せたいページでは swr の方が扱いやすいです。

SPA・noScripts ページのHTML

ssr: false のページは、中身が空の <div id="__nuxt"></div> とJSだけが返ります。検索エンジン向けの本文はHTMLに含まれません。

<body><div id="__nuxt"></div><div id="teleports"></div><script>window.__NUXT__={};...</script>
<script type="application/json" data-nuxt-data="nuxt-app" data-ssr="false" id="__NUXT_DATA__">[{"serverRendered":1},false]</script></body>

noScripts: true のページは逆に、本文はあるが <script> が1つもない HTMLになりました。ボタンなどの操作は動かなくなるので、読むだけのページ向けです。

<!DOCTYPE html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"></head><body><div id="__nuxt"><div><header>default</header><!--[--><main><h1>lite</h1><p id="rendered">2026-09-29T10:24:39.472Z</p></main><!--]--></div></div><div id="teleports"></div></body></html>

SWRで表示時刻が更新される間隔を実測

swr: 10 の /swr に2秒おきにリクエストし、HTMLに埋め込まれた時刻(=HTMLが作られた時刻)を読み取りました。

for i in $(seq 0 12); do
  r=$(curl -s localhost:7450/swr | grep -o 'id="rendered">[^<]*' | cut -d'>' -f2)
  echo "request $(date -u +%H:%M:%S) -> rendered ${r:11:8}"
  sleep 2
done
request 10:24:43 -> rendered 10:24:33
request 10:24:45 -> rendered 10:24:33
request 10:24:47 -> rendered 10:24:45
request 10:24:49 -> rendered 10:24:45
request 10:24:51 -> rendered 10:24:45
request 10:24:53 -> rendered 10:24:45
request 10:24:55 -> rendered 10:24:45
request 10:24:57 -> rendered 10:24:55
request 10:24:59 -> rendered 10:24:55
request 10:25:01 -> rendered 10:24:55
request 10:25:03 -> rendered 10:24:55
request 10:25:05 -> rendered 10:24:55
request 10:25:07 -> rendered 10:25:05

読み取れることは次のとおりです。

  • 10秒を過ぎた最初のリクエスト(10:24:45)には古いHTML(10:24:33)が返り、その裏で作り直しが始まる
  • 次のリクエスト(10:24:47)から新しいHTML(10:24:45)が返る
  • その後も約10秒ごとに更新(10:24:45 → 10:24:55 → 10:25:05)

「利用者を待たせない代わりに、期限切れ直後の1回だけ古い版を見せる」のがSWRです。

SSR・ISR(Node.js)・cache と並べて比較

同じ方法で /ssr・/isr・/cached(maxAge: 5, swr: false)を比べました。

request 10:25:16 ssr=10:25:16 isr=10:25:16 cached=10:25:16
request 10:25:18 ssr=10:25:19 isr=10:25:19 cached=10:25:16
request 10:25:21 ssr=10:25:21 isr=10:25:21 cached=10:25:16
request 10:25:23 ssr=10:25:23 isr=10:25:23 cached=10:25:23
request 10:25:25 ssr=10:25:25 isr=10:25:25 cached=10:25:23
request 10:25:27 ssr=10:25:27 isr=10:25:27 cached=10:25:23
request 10:25:29 ssr=10:25:29 isr=10:25:29 cached=10:25:29
request 10:25:31 ssr=10:25:31 isr=10:25:31 cached=10:25:29
ルール 結果 解釈
なし(SSR) 毎回新しい リクエストのたびに描画
isr: 60(Node.js) 毎回新しい Node.jsサーバーではCDNがないため、キャッシュされない
cache: { maxAge: 5, swr: false } 約5〜6秒ごとに更新 期限切れ時は古い版を返さず、作り直してから返す

Node.jsサーバーで「キャッシュしたい」なら isr ではなく swr か cache を使う、というのが実測からの結論です。

ISR・SWRページは _payload.json も作られる

Nuxt 4.3で、ISR・SWR・cache のルートでも ペイロード(_payload.json)が抽出されるようになりました。実際に取得できました。

== /swr/_payload.json
HTTP/1.1 200 OK
cache-control: s-maxage=10, stale-while-revalidate
content-type: application/json;charset=utf-8
[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"swr":3},{"now":4},"2026-09-29T10:25:39.219Z"]

== /ssr/_payload.json
HTTP/1.1 404 Page not found: /ssr/_payload.json

SWRページのHTMLには <link rel="preload" as="fetch" href="/swr/_payload.json?_b=..."> が入り、ページ移動のときにAPIを呼び直さずキャッシュ済みのデータを使います。通常のSSRページには _payload.json はありません。

nuxt generate で全ページを静的化したときの出力

npx nuxt generate(=nuxt build --prerender)を同じ設定で実行すると、ルールに関係なく全ページが静的HTMLになります。

[nitro] i Prerendering 3 initial routes with crawler
[nitro]   ├─ /200.html (71ms)
[nitro]   ├─ /404.html (72ms)
[nitro]   ├─ / (117ms)
[nitro]   ├─ /admin (35ms)
[nitro]   ├─ /spa (34ms)
[nitro]   ├─ /old-page (17ms)
[nitro]   ├─ /moved (1ms)
[nitro]   ├─ /isr (59ms)
[nitro]   ├─ /lite (60ms)
[nitro]   ├─ /ssr (61ms)
[nitro]   ├─ /swr (64ms)
[nitro]   ├─ /cached (63ms)
(_payload.json の行は省略)
[nitro] i Prerendered 18 routes in 1.741 seconds
[nitro] √ Generated public .output/public
[nitro] √ You can preview this build using npx serve .output/public
.output/public/200.html
.output/public/404.html
.output/public/_payload.json
.output/public/admin/index.html
.output/public/cached/index.html
.output/public/index.html
.output/public/isr/index.html
.output/public/lite/index.html
.output/public/moved/index.html
.output/public/old-page/index.html
.output/public/spa/index.html
.output/public/ssr/index.html
.output/public/swr/index.html
(各フォルダの _payload.json は省略)

nuxt generate ならではの変換が3つ見られました。

元のルール generate後 注意点
redirect <meta http-equiv="refresh" content="0; url=/ssr"> だけのHTML 301/307のステータスは返らない。恒久的な移転はホスティング側のリダイレクト設定で
ssr: false 中身が空の <div id="__nuxt"></div> のHTML SPAとしてブラウザで描画される
swr / isr / なし ビルド時点の内容で固定されたHTML ビルドし直すまで更新されない

/200.html と /404.html は、静的ホスティングで SPAのフォールバックや404ページとして使うファイルです。

<!-- .output/public/moved/index.html -->
<!DOCTYPE html><html><head><meta http-equiv="refresh" content="0; url=/ssr"></head></html>

nuxt build と nuxt generate の使い分けは次のとおりです。

コマンド 出力 必要な環境 routeRules
nuxt build .output/server(Nitroサーバー)+ .output/public Node.js などのサーバー、またはサーバーレス すべて有効
nuxt generate .output/public の静的ファイルのみ 静的ホスティングだけでよい redirect は meta refresh に、SWR・ISRは無効

デプロイ先ごとのISR・SWRの違い

同じ設定を Vercel向け(NITRO_PRESET=vercel)と Netlify向け(NITRO_PRESET=netlify)でビルドし、生成物を確認しました。実際のデプロイは行っていません(ビルド成果物とNitroのプリセットのコードで確認)。

デプロイ先 isr: 60 swr: 10 確認したこと
Node.js(node-server) キャッシュなし(SSRと同じ) Nitroがサーバー内でキャッシュ 上の実測
Vercel ISR関数+{"expiration": 60} ISR関数+{"expiration": false}(期限なし) .vercel/output/functions/*.prerender-config.json
Netlify Netlify-CDN-Cache-Control: public, max-age=60, stale-while-revalidate=31536000, durable を付与 Nitroの cache-control のまま Nitroのnetlifyプリセットのコード

Vercel向けビルドで出たファイルと警告です。

.vercel/output/functions/isr-isr.func
.vercel/output/functions/isr-isr.prerender-config.json   → { "expiration": 60 }
.vercel/output/functions/swr-isr.func
.vercel/output/functions/swr-isr.prerender-config.json   → { "expiration": false }

[nitro]  WARN  Nitro now uses isr option to configure ISR behavior on Vercel. Backwards-compatible support for static and swr options within the Vercel Build Options API will be removed in the future versions. Set future.nativeSWR: true nitro config disable this warning.

Vercelで swr: 10 と書くと、互換処理により「期限なしのISR」に変換されます。 10秒ごとに更新したいつもりでも、そうならない点に注意が必要です。nitro: { future: { nativeSWR: true } } を設定して再ビルドすると、/swr は通常の関数(swr.func)になり、ISRへの変換はされませんでした。Vercelでは期限つきキャッシュは isr: 秒数 で書くのがわかりやすいです。

Netlify向けビルドでは、リダイレクトとヘッダーが dist/_redirects・dist/_headers に書き出されました。

# dist/_redirects
/moved  /ssr    301
/old-page   /   302

文字列だけの redirect(Node.jsでは307)は、Netlifyの _redirects では302として出力されていました。ステータスコードを揃えたい場合は { to, statusCode } で明示します。

ページ側で書く defineRouteRules(実験的機能)

nuxt.config.ts ではなくページのファイルにルールを書く方法もあります。現時点では実験的機能で、experimental.inlineRouteRules: true が必要です(この記事では実行していません。公式ドキュメント準拠)。

// nuxt.config.ts
export default defineNuxtConfig({
  experimental: { inlineRouteRules: true },
})
<!-- app/pages/about.vue -->
<script setup lang="ts">
defineRouteRules({ prerender: true })
</script>

ページが増えるとルールが分散して見通しが悪くなるため、チーム開発では nuxt.config.ts にまとめる方が一覧性は高いです。

よくあるつまずきと対処

症状 原因 対処
isr を書いたのにNode.jsサーバーでキャッシュされない ISRはCDN(Vercel・Netlify)向けの機能 Node.jsでは swr か cache を使う
Vercelで swr のページが更新されない swr が期限なしISRに変換される isr: 秒数 で書く。または nitro.future.nativeSWR: true
nuxt generate 後にリダイレクトが301にならない 静的ファイルでは meta refresh になる ホスティングのリダイレクト設定を使う
ssr: false のページが検索結果に出ない HTMLに本文がない 検索に載せたいページはSSRかprerenderに
prerenderしたページのデータが古い ビルド時点で固定される 再ビルドするか、swr・isr に変える
curl -I /api/now が404になる now.get.ts はGET専用で、-I(HEAD)には一致しない curl -s -D - -o /dev/null でGETのヘッダーを見る
動的ルートがprerenderされない リンクがなくクローラーが見つけられない nitro.prerender.routes か prerenderRoutes() で列挙

最後の curl -I の件は実測で遭遇しました。server/api/now.get.ts に curl -I を送ると 404 Page not found: /api/now でしたが、GETで取得すると 200 と正しいヘッダーが返りました。

よくある質問

Q. Nuxtの既定のレンダリング方式は何ですか? A. SSR(ユニバーサルレンダリング)です。nuxt.config.ts で ssr: false を書くとアプリ全体がSPAになり、routeRules の ssr: false なら指定したパスだけがSPAになります。

Q. SWRとISRはどちらを使えばよいですか? A. Node.jsサーバーやDockerで運用するならSWR、Vercel・NetlifyならISRが目安です。今回の実測では、Node.jsで isr: 60 を指定してもキャッシュされず、swr: 10 は約10秒ごとに更新されました。

Q. nuxt generate と prerender: true の違いは? A. nuxt generate は全ページを静的化し、サーバーなしで配信します。prerender: true は指定したページだけを静的化し、残りはサーバーで動かすハイブリッド構成です。

Q. Next.jsのISRとの違いは? A. 考え方は近く、Next.jsはページやfetch単位の revalidate、Nuxtは URLパターン単位の routeRules で指定します。Nuxtはキャッシュの実体がデプロイ先のプリセットで変わる点が特徴です。

まとめ

  • routeRules でURLごとにSSR・SPA・SSG・SWR・ISRを選べる(ハイブリッドレンダリング)
  • 既定はSSR。更新が少ないページは prerender: true、管理画面は ssr: false
  • swr は s-maxage、cache は max-age を付与。SWRは期限切れ直後の1回だけ古い版を返し、裏で作り直す
  • Node.jsで isr はキャッシュされない。Node.jsなら swr / cache、Vercel・Netlifyなら isr
  • Vercelで swr は期限なしISRに変換されるため、期限つきは isr: 秒数 で書く
  • nuxt generate ではリダイレクトが meta refresh になり、SWR・ISRは使えない
  • 設定したら curl でヘッダーとHTMLの生成時刻を確かめると、意図どおりか一目でわかる

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「Nuxt SSR・SSGの設定|routeRules全オプションとヘッダー実測」

株式会社RJCでは、フレームワークの設定を「書いて終わり」にせず、実際のヘッダーや出力で確かめる習慣をプロジェクトの中で仲間と共有しています。こうした知識を共有しながら、日々技術を磨いています。

株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。

WE ARE HIRING

RJCで一緒に開発しながら、
成長を楽しみませんか?

RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!

  • 127日年間休日
  • 12時間平均残業時間
  • 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!

ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。

ABOUT RJC RJCがどんな会社か知る 考え方、研修、働き方、福利厚生、社員の前職まで。RJCのことが丸わかり! RJC丸わかりページへ JOB DESCRIPTION 仕事内容・待遇を見てみる 仕事内容、給与・待遇、選考の流れ。経験者も未経験も!応募前に知りたいこと、まとめました! 募集要項を見る ENTRY エントリーする エントリーは1〜2分・履歴書不要です。まずは話を聞いてみたい、という方でも歓迎です! エントリーフォームへ

RJCで一緒に開発しながら、 成長を楽しみませんか?