メインコンテンツまでスキップ

Static Exports

Next.jsは、静的サイトやシングルページアプリケーション(SPA)として開始し、後でサーバーを必要とする機能をオプションで利用することにより拡張することができます。

next buildを実行すると、Next.jsはルートごとにHTMLファイルを生成します。厳密なSPAを個別のHTMLファイルに分割することで、Next.jsはクライアント側で不要なJavaScriptコードの読み込みを避け、バンドルサイズを削減し、ページの読み込みを速くします。

Next.jsはこの静的エクスポートをサポートしているため、HTML/CSS/JSの静的アセットを提供できる任意のWebサーバーにデプロイしてホスティングすることができます。

設定

静的エクスポートを有効にするには、next.config.js内で出力モードを変更します:

next.config.js
/**
* @type {import('next').NextConfig}
*/
const nextConfig = {
output: 'export',

// オプション: リンクを `/me` -> `/me/`に変更し、`/me.html` -> `/me/index.html`を出力
// trailingSlash: true,

// オプション: 自動的な`/me` -> `/me/`を防ぎ、`href`を保持
// skipTrailingSlashRedirect: true,

// オプション: 出力ディレクトリを`out` -> `dist`に変更
// distDir: 'dist',
}

module.exports = nextConfig

next buildを実行した後、Next.jsはアプリケーションのHTML/CSS/JSアセットを含むoutフォルダを生成します。

サポートされている機能

Next.jsのコアは静的エクスポートをサポートするように設計されています。

Server Components

静的エクスポートを生成するためにnext buildを実行すると、appディレクトリ内で使用されるServer Componentsは、従来の静的サイト生成と同様にビルド中に実行されます。

結果として得られるコンポーネントは、初期ページロード用の静的HTMLと、ルート間のクライアントナビゲーション用の静的ペイロードとしてレンダリングされます。静的エクスポートを使用する際、Server Componentsを変更する必要はありません。ただし、dynamic server functionsを使用する場合を除きます。

app/page.tsx
export default async function Page() {
// このフェッチは`next build`時にサーバーで実行されます
const res = await fetch('https://api.example.com/...')
const data = await res.json()

return <main>...</main>
}

Client Components

クライアントでデータフェッチを行いたい場合、Client ComponentをSWRと組み合わせてリクエストをメモ化することができます。

app/other/page.tsx
'use client'

import useSWR from 'swr'

const fetcher = (url: string) => fetch(url).then((r) => r.json())

export default function Page() {
const { data, error } = useSWR(
`https://jsonplaceholder.typicode.com/posts/1`,
fetcher
)
if (error) return 'Failed to load'
if (!data) return 'Loading...'

return data.title
}

ルート遷移はクライアント側で行われるため、これは従来のSPAのように動作します。例えば、次のインデックスルートでは、クライアント上で異なる投稿にナビゲートできます:

app/page.tsx
import Link from 'next/link'

export default function Page() {
return (
<>
<h1>Index Page</h1>
<hr />
<ul>
<li>
<Link href="/post/1">Post 1</Link>
</li>
<li>
<Link href="/post/2">Post 2</Link>
</li>
</ul>
</>
)
}

画像最適化

next/imageを使用した画像最適化を静的エクスポートで利用するためには、next.config.jsでカスタム画像ローダーを定義できます。例えば、Cloudinaryのようなサービスで画像を最適化することができます:

next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
output: 'export',
images: {
loader: 'custom',
loaderFile: './my-loader.ts',
},
}

module.exports = nextConfig

このカスタムローダーは、リモートソースから画像を取得する方法を定義します。例えば、次のローダーはCloudinary用のURLを構築します:

my-loader.ts
export default function cloudinaryLoader({
src,
width,
quality,
}: {
src: string
width: number
quality?: number
}) {
const params = ['f_auto', 'c_limit', `w_${width}`, `q_${quality || 'auto'}`]
return `https://res.cloudinary.com/demo/image/upload/${params.join(
','
)}${src}`
}

その後、next/imageを使用して、Cloudinary内の画像への相対パスを定義します:

app/page.tsx
import Image from 'next/image'

export default function Page() {
return <Image alt="turtles" src="/turtles.jpg" width={300} height={300} />
}

Route Handler

Route Handlerは、next buildを実行すると静的なレスポンスをレンダリングします。サポートされているのはGETHTTPメソッドのみです。これを使用して、キャッシュされたまたはキャッシュされていないデータから静的なHTML、JSON、TXT、またはその他のファイルを生成できます。例えば:

app/data.json/route.ts
export async function GET() {
return Response.json({ name: 'Lee' })
}

上記のファイルapp/data.json/route.tsnext build中に静的ファイルにレンダリングされ、data.json{ name: 'Lee' }が含まれます。

受信リクエストから動的な値を読み取る必要がある場合、静的エクスポートを使用することはできません。

ブラウザーAPI

Client Componentはnext build時にHTMLに事前レンダリングされます。windowlocalStoragenavigatorなどのWeb APIはサーバーで使用できないため、ブラウザーで実行される際にこれらのAPIに安全にアクセスする必要があります。例えば:

'use client';

import { useEffect } from 'react';

export default function ClientComponent() {
useEffect(() => {
// ここで`window`へのアクセスが可能です
console.log(window.innerHeight);
}, [])

return ...;
}

サポートされていない機能

Node.jsサーバーが必要な機能や、ビルドプロセス中に計算できない動的ロジックはサポートされていません

これらの機能のいずれかをnext devで使用しようとすると、root layoutdynamicオプションをerrorに設定した場合と同様にエラーが発生します。

export const dynamic = 'error'

デプロイ

静的エクスポートを使用すると、HTML/CSS/JSの静的アセットを提供できる任意のWebサーバーにNext.jsをデプロイしてホスティングすることができます。

next buildを実行すると、Next.jsはoutフォルダに静的エクスポートを生成します。例えば、次のようなルートがあるとします:

  • /
  • /blog/[id]

next buildを実行した後、Next.jsは以下のファイルを生成します:

  • /out/index.html
  • /out/404.html
  • /out/blog/post-1.html
  • /out/blog/post-2.html

Nginxのような静的ホストを使用している場合、書き換えを設定して受信リクエストを適切なファイルにリダイレクトできます:

nginx.conf
server {
listen 80;
server_name acme.com;

root /var/www/out;

location / {
try_files $uri $uri.html $uri/ =404;
}

# `trailingSlash: false`の場合に必要です。
# `trailingSlash: true`の場合、省略可能です。
location /blog/ {
rewrite ^/blog/(.*)$ /blog/$1.html break;
}

error_page 404 /404.html;
location = /404.html {
internal;
}
}

バージョン履歴

バージョン変更点
v14.0.0next export が削除され、"output": "export"に置き換えられました
v13.4.0App Router (Stable)が、React Server ComponentsとRoute Handlerの使用を含む拡張された静的エクスポートサポートを追加しました
v13.3.0next export は非推奨になり、"output": "export" に置き換えられました