Next.jsの公式チュートリアルに従いプロジェクトを作成すると、既定でSPAをビルドする環境にはなっていない。
「ちょっとしたツールをつくりたいんじゃ」という場合に筆者はよくSPAを作りたくなるが、
Next.jsでSPAを作る環境を整備する上で、筆者のような初心者がつまづくポイントがいくつかあるので、
筆者が手探りで見つけた対応方法の一例をメモしておく。
必要な前提知識
- HTML/CSS/JavaScriptの基本的な実装方法
- Node.jsにおけるJavaScript開発作法:import文
- npm/npxの基本的な使い方
- Reactの関数コンポーネントによるGUIの基本的な実装方法
- TypeScriptの基礎知識(無くても一応環境整備だけならできる)
必要な前提環境
- OSは Linux/Windows 10/Windows 11/macOS いずれでもOK
- 筆者の環境は Ubuntu 22.04 64bit(Linux)
- Node.js v16.8.0以上
- 筆者の環境は v18.16.0(fnmを使っているがこの辺りは使いたければお好みで)
- npmはNode.jsに同梱のバージョン
- 筆者の環境は 9.5.1
- npxもNode.jsに同梱のバージョン
- 筆者の環境は 9.5.1
ベースとなるプロジェクトの作成
まずは公式チュートリアルの説明に則り、プロジェクトのスタートとなるコードを用意する。
この記事ではnpmパッケージの個々のバージョン指定を詳しく説明するつもりはないので、
ひとまず現時点の最新版を使う前提で考える。
ソースコードを置きたいフォルダを用意し、そのフォルダ直下でコンソール(ターミナル/コマンドプロンプト/PowerShellなど)を開く。
コンソールで次のコマンドを実行する。
npx create-next-app@latest --typescript
コマンド実行後にいくつか設定項目を質問される。
それら項目のうち、この記事に関係しそうなところで筆者が指定した内容は次の通り。
Would you like to use `src/` directory with this project? –> Yes
Use App Router (recommanded)? –> No
Would you like to customize the default import alias? –> No
静的HTMLファイルの出力設定
自動生成された package.json の “scripts” 項目に、既定のコマンドがいくつか用意されているが、
そこには静的HTMLファイルを出力するコマンドが無いので、
以下の手順で自分で用意する。
自動生成された package.json の抜粋:
{
(中略)
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint"
},
(中略)
}
まず、buildコマンドの既定の動きを静的HTMLファイルの出力に切り替えるため、プロジェクトのルートディレクトリにある next.config.js ファイルに output の設定を追加する。
画像の最適化処理もSPAでは不要なので、unoptimizedパラメータも true に設定しておく。
next.config.js ファイルの中身:
/** @type {import('next').NextConfig} */
const nextConfig = {
/* ここから追加分
output: 'export',
images: {
unoptimized: true
},
ここまで追加分 */
reactStrictMode: true
}
module.exports = nextConfig
これにより、コンソールで npm run build
コマンドを実行すると、out/
ディレクトリ以下に静的HTMLファイルが出力されるようになる。
しかし、この時点ではCSSファイルのパス設定が不適切なので、画面にCSSスタイルが当たらない。
以下でパス設定をする。
デバッグ環境/本番環境のパス切替設定
Next.jsではCSS等のパスを相対パスで指定できない。(vue-cliでは普通にできていたので筆者が結構ハマったポイント)
必ずスラッシュ “/” から始まる絶対パスで指定する必要があるため、一般的にはデバッグ環境と本番環境とでパスが切り替えられる作りにするようだ。
具体的には next.config.js ファイルに次の例の要領で設定を追加する。
/** @type {import('next').NextConfig} */
const isDevelopmet = process.env.NODE_ENV !== 'production' // 追記1
const nextConfig = {
output: 'export',
images: {
unoptimized: true
},
assetPrefix: isDevelopment ? '' : '/sample/', // 追記2
reactStrictMode: true
}
module.exports = nextConfig
「追記1」では、ビルドがデバッグ用なのか本番環境用なのかを区別するためのパラメータを取得している。
isDevelopment が true ならデバッグ用、false なら本番環境用だ。
「追記2」では、三項演算子を用いてパス設定を分岐している。
デバッグ用のビルドの場合、パスは ” (空の文字列)にしておけばとりあえずOK。
このパスは、npm run dev
コマンドを実行したときに使われる。
本番環境の場合、パスは環境により異なるが、例えばこのブログの
https://slash-mochi.net/sample/index.html
というURLで開発物を公開する場合、指定するパスは
'/sample/'
となる。(自身のWebサーバーの設定を確認しておくこと)
このパスは npm run build
コマンドを実行したときに使われる。
API Routeの削除
静的HTMLファイルを出力するモードではAPI Routeは使えないため、
src/pages/api
ディレクトリを丸ごと削除する。
デバッグ実行手順
package.jsonファイルがあるディレクトリで次のコマンドを実行する。
npm run dev
コンソールに表示されるリンク http://localhost:3000
を開くか、あるいは
WebブラウザのURL入力欄に http://localhost:3000
と入力してページを開くと、
開発中の画面を表示できる。
Webブラウザの開発用ツールで種々のデバッグ操作が行える。
本番用ビルド・デプロイ手順
package.jsonファイルがあるディレクトリで次のコマンドを実行する。
npm run build
コマンド実行後、out/
ディレクトリ以下に静的HTMLファイルが出力される。
out/
ディレクトリ以下のすべてのファイル・フォルダを本番環境にコピーし、
Webブラウザから本番環境にアクセスして画面が表示されることを確認する。