Next.jsを利用して実装したウェブサイトをSSGへ移行したときのつまづき
環境
code:bash
$ yarn --version
1.22.19
code:json
{"dependencies": {
"@types/node": "20.4.5",
"@types/react": "18.2.16",
"@types/react-dom": "18.2.7",
"eslint": "8.45.0",
"eslint-config-next": "13.4.12",
"next": "13.4.12",
"react": "18.2.0",
"react-dom": "18.2.0",
"typescript": "5.1.6"
}}
モチベーション
イベントハンドラやHooks等クライアントの機能を使いたいわけではなかったので、Server Componentsのみで実装した
コンテンツの更新頻度がそこまで高くない、静的なサイトだし、SSGでよくね?と思った
方法
公式ドキュメントにある通り、 next.config.jsを変更すればOK
code:js
/** @type {import('next').NextConfig} */
-const nextConfig = {}
+const nextConfig = {
+ output: "export",
+};
これで $ next build した際に、静的なhtml, js, cssファイルが吐き出される
起こったこと
$ next build 時にルートとなる index.html が生成されない
というよりも、Server Componentとして生成されている?
code:bash
$ next build
🐼 info hrtime Extracted in (30.77ms) - info Creating an optimized production build
- info Compiled successfully
- info Linting and checking validity of types
- info Collecting page data
- info Generating static pages (4/4)
- info Finalizing page optimization
Route (app) Size First Load JS
┌ λ / 137 B 78.3 kB
└ ○ /favicon.ico 0 B 0 B
+ First Load JS shared by all 78.1 kB
├ chunks/596-dca21600ca7eea8c.js 25.8 kB
├ chunks/fd9d1056-5fc0659828b82348.js 50.5 kB
├ chunks/main-app-191d09eed3488dd7.js 214 B
└ chunks/webpack-930a7b18ee1f131d.js 1.64 kB
Route (pages) Size First Load JS
─ ○ /404 182 B 75.6 kB
+ First Load JS shared by all 75.4 kB
├ chunks/framework-8883d1e9be70c3da.js 45 kB
├ chunks/main-1710cefc469e610b.js 28.5 kB
├ chunks/pages/_app-52924524f99094ab.js 195 B
└ chunks/webpack-930a7b18ee1f131d.js 1.64 kB
λ (Server) server-side renders at runtime (uses getInitialProps or getServerSideProps)
○ (Static) automatically rendered as static HTML (uses no initial props)
原因
外部APIへのアクセスでfetchを行う時にキャッシュを毎回破棄する設定をしていた
code: typescript
const articles = await fetch(
https://scrapbox.io/api/pages/${scrapboxAccount}?skip=1&limit=7,
{ cache: 'no-cache' }
).then((res) => res.json());
no-cache をつけてるってことはキャッシュを生成しない=毎回リクエストを行って最新のコンテンツを取得することを意図しているってことかしら
Features that require a Node.js server, or dynamic logic that cannot be computed during the build process, are not supported:
(中略)
- Incremental Static Regeneration
Incremental Static Regenerationのなかにfetchが含まれており、no-cache もしくはNext.jsで拡張、追加された no-storeを指定するとこれにあたるのかな。
対応
fetch APIのcacheオプションを変更した
no-cache等キャッシュを全くしないオプションでなければ良さそう
code:typescript
const articles = await fetch(
https://scrapbox.io/api/pages/${scrapboxAccount}?skip=1&limit=7,
{ next: { revalidate: 300 } }
).then((res) => res.json());
その他
静的なサイトの場合、$ next start すると怒られてしまうので、何かしら他の方法でサーブする必要がある
code:bash
$ next start -p 8080
Error: "next start" does not work with "output: export" configuration. Use "npx serve@latest out" instead.
at /home/iwhammy/source/work/i-whammy.dev/node_modules/next/dist/server/next.js:197:31
at async NextServer.prepare (/home/iwhammy/source/work/i-whammy.dev/node_modules/next/dist/server/next.js:161:24)
at async Server.<anonymous> (/home/iwhammy/source/work/i-whammy.dev/node_modules/next/dist/server/lib/render-server.js:136:17) {
type: 'Error'
}
error Command failed with exit code 1.
今回は $ npx serve@latest out した