コンテンツへスキップ

静的エクスポート

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',
 
  // Optional: Change links `/me` -> `/me/` and emit `/me.html` -> `/me/index.html`
  // trailingSlash: true,
 
  // Optional: Prevent automatic `/me` -> `/me/`, instead preserve `href`
  // skipTrailingSlashRedirect: true,
 
  // Optional: Change the output directory `out` -> `dist`
  // distDir: 'dist',
}
 
module.exports = nextConfig

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

サポートされている機能

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

サーバーコンポーネント

next build を実行して静的エクスポートを生成すると、app ディレクトリ内で消費されるサーバーコンポーネントは、従来の静的サイト生成と同様に、ビルド中に実行されます。

結果のコンポーネントは、最初のページ読み込みのために静的な HTML にレンダリングされ、ルート間のクライアントナビゲーションのために静的なペイロードにレンダリングされます。静的エクスポートを使用する場合、動的なサーバー関数を消費しない限り、サーバーコンポーネントに必要な変更はありません。

app/page.tsx
export default async function Page() {
  // This fetch will run on the server during `next build`
  const res = await fetch('https://api.example.com/...')
  const data = await res.json()
 
  return <main>...</main>
}

クライアントコンポーネント

クライアントでデータフェッチを実行する場合は、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} />
}

ルートハンドラー

ルートハンドラーは、next build の実行時に静的レスポンスをレンダリングします。GET HTTP 動詞のみがサポートされています。これは、キャッシュされたデータまたはキャッシュされていないデータから、静的なHTML、JSON、TXT、またはその他のファイルを生成するために使用できます。例:

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

上記のファイル app/data.json/route.ts は、next build 時に静的ファイルにレンダリングされ、{ name: 'Lee' } を含む data.json が生成されます。

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

ブラウザAPI

クライアントコンポーネントは、next build 中にHTMLにプリレンダリングされます。windowlocalStoragenavigator のようなWeb APIはサーバーでは利用できないため、ブラウザで実行している場合にのみ、これらのAPIに安全にアクセスする必要があります。例:

'use client';
 
import { useEffect } from 'react';
 
export default function ClientComponent() {
  useEffect(() => {
    // You now have access to `window`
    console.log(window.innerHeight);
  }, [])
 
  return ...;
}

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

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

これらの機能を next dev で使用しようとすると、ルートレイアウトでdynamic オプションを error に設定するのと同様のエラーが発生します。

export const dynamic = 'error'

デプロイ

静的エクスポートでは、Next.jsはHTML/CSS/JS静的アセットを提供できる任意のWebサーバーにデプロイおよびホストできます。

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;
  }
 
  # This is necessary when `trailingSlash: false`.
  # You can omit this when `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 とルートハンドラーの使用を含む、強化された静的エクスポートのサポートを追加します。
v13.3.0next export は非推奨となり、"output": "export" に置き換えられました。