Next.js 14のSSGの環境構築

これはなに Link to this heading

Next.js 14のSSGの環境構築をしたときのメモ。

環境 Link to this heading

  • WSL2 Ubuntu 22.04.2 LTS

  • Docker version 24.0.6

  • VS Code 1.84.0

  • Next 14.0.1

環境構築 Link to this heading

Dockerfiledevcontainer.jsonを作って環境を構築する。

.devcontainer/Dockerfile
FROM node:20-slim

EXPOSE 3000

RUN apt-get update -y \
    && DEBIAN_FRONTEND=noninteractive \
    apt-get install -y --no-install-recommends \
    git \
    locales \
    tzdata \
    xsel \
    && apt-get clean \
    && rm -rf /var/lib/apt/lists/*

RUN locale-gen ja_JP.UTF-8 \
    && localedef -f UTF-8 -i ja_JP ja_JP.UTF-8
ENV TZ=Asia/Tokyo \
    LANG=ja_JP.UTF-8 \
    LANGUAGE=ja_JP:jp \
    LC_ALL=ja_JP.UTF-8

RUN npm install -g npm

USER node
.devcontainer/devcontainer.json
{
  "build": {
    "dockerfile": "./Dockerfile",
    "context": ".."
  },
  "forwardPorts": [
    3000
  ],
  "customizations": {
    "vscode": {
      "extensions": [
        "PulkitGangwar.nextjs-snippets",
        "dbaeumer.vscode-eslint",
        "esbenp.prettier-vscode"
      ]
    }
  }
}

必須の拡張機能はdevcontainer.jsonに書く。必須でないものは.vscode/extensions.jsonに記述する。.vscode/extensions.jsonに記述した後、VS Codeの拡張機能のタブにて@recommendedで検索すると、ワークスペースの推奨事項にそれらの拡張機能が表示される。

.vscode/extensions.json
{
  "recommendations": [
    "oderwat.indent-rainbow", // インデントに色を付ける
    "mohammadbaqer.better-folding", // 折り畳みを見やすくする
    "streetsidesoftware.code-spell-checker", // スペルチェック
    "naumovs.color-highlight", // カラーコードをその色でハイライト
    "igorsbitnev.error-gutters", // エラーが出ている横にアイコンをつける
    "saikou9901.evilinspector", // 全角スペース強調
    "mhutchie.git-graph", // Gitのコミット履歴を見やすくできる
    "donjayamanne.githistory", // ファイルごとの変更履歴を見やすくできる
    "github.copilot", // コード書くときのサポーター(有料)
    "kisstkondoros.vscode-gutter-preview",
    "christian-kohler.path-intellisense",
    "gruntfuggly.todo-tree", // TODOの強調
    "shardulm94.trailing-spaces", // 行末の半角スペース強調
    "visualstudioexptteam.vscodeintellicode" // TypeScript書くときに補助してくれる
  ]
}

VS Code拡張機能のDev Containersをローカルにインストールする。その後、Ctrl + Shift + Pでコマンドパレットを開き、Dev Containers: Reopen in Containerを実行する。これにより、Dockerfileがビルドされ、VS Codeがコンテナにアタッチされる。

Node.js環境の確認 Link to this heading

コンテナにアタッチされたVS Codeのターミナルで、node -vnpm -vを実行する。

$ node -v
v20.9.0
$ npm -v
10.2.3

Git管理する Link to this heading

プロジェクトをgit管理下に置く。

git init

branch名をデフォルトでmainにしていない場合はwarningが出るので、mainにしておく。

git branch -m main

アプリのひな型を作成する Link to this heading

Next.jsのアプリのひな型を作る。下記コマンドを実行する。

npx create-next-app@latest

プロジェクトの設定をいろいろ聞かれるので答える。

設定選択

コンソール出力のログ

$ npx create-next-app@latest
Need to install the following packages:
create-next-app@14.0.1
Ok to proceed? (y) y
✔ What is your project named? … next-app
✔ Would you like to use TypeScript? … No / Yes
✔ Would you like to use ESLint? … No / Yes
✔ Would you like to use Tailwind CSS? … No / Yes
✔ Would you like to use `src/` directory? … No / Yes
✔ Would you like to use App Router? (recommended) … No / Yes
✔ Would you like to customize the default import alias (@/*)? … No / Yes
Creating a new Next.js app in /workspaces/path/next-app.

Using npm.

Initializing project with template: app-tw


Installing dependencies:
- react
- react-dom
- next

Installing devDependencies:
- typescript
- @types/node
- @types/react
- @types/react-dom
- autoprefixer
- postcss
- tailwindcss
- eslint
- eslint-config-next


added 331 packages, and audited 332 packages in 25s

116 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities
Success! Created next-app at /workspaces/path/next-app

すると、プロジェクト名(上記だとnext-app)のディレクトリが作成され、アプリのひな形が作られる。下記コマンドで起動するか確認する。

cd next-app
npm run dev

http://localhost:3000にアクセスして、下記のようなデフォルトページが表示されることを確認する。

デフォルトのページ

ページの表示はCtrl + Cで終了できる。

SSGのためのプロジェクトの設定を変更する Link to this heading

next.config.jsを変更し、reactStrictModeを有効にしておく。

next.config.js Options: reactStrictMode | Next.js's image

next.config.js Options: reactStrictMode | Next.js

The complete Next.js runtime is now Strict Mode-compliant, learn how to opt-in

nextjs.org favicon image nextjs.org

また、静的サイトにするため、output: 'export'を追加する。

Guides: Static Exports | Next.js's image

Guides: Static Exports | Next.js

Next.js enables starting as a static site or Single-Page Application (SPA), then later optionally upgrading to use features that require a server.

nextjs.org favicon image nextjs.org

変更後のnext.config.jsは下記のとおり。

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

module.exports = nextConfig

静的サイトの場合は、output: 'export'を設定した後にnpm run buildし、これにより、npx serve@latest outすることでビルドした静的サイトをプレビューできる。

npm run build
npm run buildのログ

$ npm run build

> next-app@0.1.0 build
> next build

   ▲ Next.js 14.0.1

 ✓ Creating an optimized production build
 ✓ Compiled successfully
 ✓ Linting and checking validity of types
 ✓ Collecting page data
 ✓ Generating static pages (5/5)
 ✓ Finalizing page optimization

Route (app)                              Size     First Load JS
┌ ○ /                                    5.28 kB        90.4 kB
└ ○ /_not-found                          882 B            86 kB
+ First Load JS shared by all            85.2 kB
  ├ chunks/472-39c72660b90e2701.js       30 kB
  ├ chunks/fd9d1056-39de21f001c52188.js  53.2 kB
  ├ chunks/main-app-5c586790629e224c.js  232 B
  └ chunks/webpack-2f0f07802d1106cf.js   1.69 kB


(Static)  prerendered as static HTML

npx serve@latest out
npx serve@latest outのログ

$ npx serve@latest out
Need to install the following packages:
serve@14.2.1
Ok to proceed? (y) y

   ┌────────────────────────────────────────┐
   │                                        │
   │   Serving!                             │
   │                                        │
   │   - Local:    http://localhost:3000    │
   │   - Network:  http://172.17.0.3:3000   │
   │                                        │
   │   Copied local address to clipboard!   │
   │                                        │
   └────────────────────────────────────────┘

 HTTP  2023/11/4 5:41:17 127.0.0.1 GET /
 HTTP  2023/11/4 5:41:17 127.0.0.1 Returned 200 in 7 ms
 HTTP  2023/11/4 5:41:17 127.0.0.1 GET /_next/static/media/c9a5bc6a7c948fb0-s.p.woff2
 HTTP  2023/11/4 5:41:17 127.0.0.1 Returned 200 in 1 ms
 ...

プレビューはCtrl + Cで終了できる。

毎回npx serve@latest outと打つのは面倒なので、package.jsonにコマンドを追加する。npm run serveでbuildした静的サイトをプレビューできる。

package.json
{
  "name": "next-app",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "next lint",
+   "serve": "npx serve@latest out"
  },
  "dependencies": {
    "react": "^18",
    "react-dom": "^18",
    "next": "14.0.1"
  },
  "devDependencies": {
    "typescript": "^5",
    "@types/node": "^20",
    "@types/react": "^18",
    "@types/react-dom": "^18",
    "autoprefixer": "^10.0.1",
    "postcss": "^8",
    "tailwindcss": "^3.3.0",
    "eslint": "^8",
    "eslint-config-next": "14.0.1"
  }
}

Linterがtsxファイルのエラーも検知するようにする Link to this heading

npm run lint(あるいはnpx next lint)を実行してもTypeScriptのコードのエラーは表示されない。これを表示されるように変更する。

Next.js ESLint で TypeScript のエラーを表示するようにしたい - かもメモ's image

Next.js ESLint で TypeScript のエラーを表示するようにしたい - かもメモ

1. Next.js はデフォルトでは TypeScript のエラーが `npm run lint` では表示されない 2. ミニマムな TypeScript のエラーを表示させるには `@typescript-eslint/eslint-plugin` をインストールして `.eslintrc.json` にルールを追加する 3. 使用するルールに依っては `.eslintrc.json` に `parserOptions.project` プロパティを作成しプロジェクトの `tsconfig.json` のパスを指定する

chaika.hatenablog.com favicon image chaika.hatenablog.com
Next.js13.4+TypeScript+ESLint+Prettier+Huskyのよくばりセットで環境を構築してみました's image

Next.js13.4+TypeScript+ESLint+Prettier+Huskyのよくばりセットで環境を構築してみました

zenn.dev favicon image zenn.dev

まず、必要なプラグインをインストールする。

npm i -D @typescript-eslint/eslint-plugin

次に、.eslintrc.jsonを変更する。extendsparserOptionsの変更は必須。他は任意。

.eslintrc.json
{
  "root": true,
  "extends": [
    "plugin:@typescript-eslint/recommended",
    "next/core-web-vitals"
  ],
  "parserOptions": {
    "project": "./tsconfig.json"
  },
  "rules": {
    "@typescript-eslint/no-unused-vars": "error",
    "@typescript-eslint/no-explicit-any": "error",
    "@typescript-eslint/no-unsafe-call": "error",
    "@typescript-eslint/no-unsafe-member-access": "error",
    "@typescript-eslint/no-unsafe-return": "error"
  }
}

ここまで設定すれば、npm run lint.tsxのエラーが表示されるようになる。これ以降の設定は、必要であれば設定する。

VSCodeの設定を変更して、linterがVS Codeでも正常に動くようにする。

.vscode/settings.json
{
  // Linter
  "eslint.workingDirectories": [
    "./next-app",
  ],
  "editor.codeActionsOnSave": {
    "source.fixAll": false,
    "source.fixAll.eslint": true
  }
}

package.jsonのlintコマンドを変更し、.gitignoreに指定しているファイルは無視するように変更する。

package.json
{
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
-   "lint": "next lint",
+   "lint": "next lint --ignore-path .gitignore",
    "serve": "npx serve@latest out"
  },
}

Prettierを入れる Link to this heading

FormatterとしてPrettierを入れる。まず、パッケージをインストールする。

npm i -D prettier eslint-config-prettier

次に、Prettierの設定ファイルを作る。この設定は好みや方針により異なる。

.prettierrc
{
  "semi": true,
  "trailingComma": "all",
  "singleQuote": true,
  "printWidth": 80,
  "tabWidth": 2
}

加えて、.eslintrc.jsonにPrettierを追加する。

.eslintrc.json
{
  "root": true,
  "extends": [
    "plugin:@typescript-eslint/recommended",
    "next/core-web-vitals",
+   "prettier"
  ],
  "parserOptions": {
    "project": "./tsconfig.json"
  },
  "rules": {
    "@typescript-eslint/no-unused-vars": "error",
    "@typescript-eslint/no-explicit-any": "error",
    "@typescript-eslint/no-unsafe-call": "error",
    "@typescript-eslint/no-unsafe-member-access": "error",
    "@typescript-eslint/no-unsafe-return": "error"
  }
}

最後に、package.jsonformatコマンドを追加する。

package.json
{
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "next lint --ignore-path .gitignore",
+   "format": "prettier --write --ignore-path .gitignore .",
    "serve": "npx serve@latest out"
  },
}

追加したらnpm run formatを実行して動作を確認する。

npm run format

VS Codeの場合は下記の設定を追加すると、保存時やタイプ時に自動でフォーマットされる。

.vscode/settings.json
{
  // formatter
  "editor.defaultFormatter": "esbenp.prettier-vscode",
  "editor.formatOnSave": true,
  "editor.formatOnPaste": true,
  "editor.formatOnType": true,
}

コミット時にlinterとformatterを自動実行する Link to this heading

コミット時にnpm run lintnpm run formatを実行し、エラーが出る場合はコミットできないようにする。

Next.js13.4+TypeScript+ESLint+Prettier+Huskyのよくばりセットで環境を構築してみました's image

Next.js13.4+TypeScript+ESLint+Prettier+Huskyのよくばりセットで環境を構築してみました

zenn.dev favicon image zenn.dev
Next.jsでhuskyを使ったcommit時lintエラー検出とGitHub Desktop対応's image

Next.jsでhuskyを使ったcommit時lintエラー検出とGitHub Desktop対応

Next.js で husky と lint-staged を使って、commit 時に ESLint エラー検出の仕組みの解説と手順です。加えて、GitHub Desktop(Windows 10 x64)でも動作するようにしました。React の場合も手順を記載しました。

itc-engineering-blog.netlify.app favicon image itc-engineering-blog.netlify.a …
husky + lint-stagedでコミット前にLinterを実行させる's image

husky + lint-stagedでコミット前にLinterを実行させる

notes.nakurei.com favicon image notes.nakurei.com

huskyとlint-stagedを入れる Link to this heading

まず、必要なパッケージをインストールする。

npm i -D husky lint-staged

次に、husky-initコマンドを実行する。環境によりコマンドが異なるため、実行するコマンドの詳細はhuskyの公式サイトを参照すること。

npx husky-init && npm install

.gitディレクトリとpackage.jsonファイルが同じ階層に存在しない場合は、下記のようなエラーが発生する。

$ npx husky-init && npm install
Need to install the following packages:
husky-init@8.0.0
Ok to proceed? (y) y
husky-init updating package.json
  setting prepare script to command "husky install"
/home/node/.npm/_npx/1ab9c0f68ac2536e/node_modules/husky/lib/index.js:23
        throw new Error(`.git can't be found (see ${url})`);
        ^

Error: .git can't be found (see https://typicode.github.io/husky/#/?id=custom-directory)
    at install (/home/node/.npm/_npx/1ab9c0f68ac2536e/node_modules/husky/lib/index.js:23:15)
    at Object.<anonymous> (/home/node/.npm/_npx/1ab9c0f68ac2536e/node_modules/husky-init/lib/bin.js:16:21)
    at Module._compile (node:internal/modules/cjs/loader:1241:14)
    at Module._extensions..js (node:internal/modules/cjs/loader:1295:10)
    at Module.load (node:internal/modules/cjs/loader:1091:32)
    at Module._load (node:internal/modules/cjs/loader:938:12)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:83:12)
    at node:internal/main/run_main_module:23:47

Node.js v20.9.0

このエラーへの対処法は、huskyの公式サイトに書かれているとおりで、npx husky-initによってpackage.jsonに追加されたprepareスクリプトを変更する。

たとえば、プロジェクト名がnext-appの場合は下記のように変更する。

package.json
{
  "scripts": {
-   "prepare": "husky install"
+   "prepare": "cd .. && husky install next-app/.husky"
  },
}

変更したら、再度npm i(あるいはnpm install)を実行する。

npm i

成功すると、.huskyディレクトリが生成される。

huskyにhookを追加する Link to this heading

.huskyディレクトリが生成されたら、自動実行のためのhookを追加する。今回は下記のコマンドでpre-commitのhookを追加する。

npx husky add .husky/pre-commit "npx lint-staged"

実行すると、.huskyディレクトリに下記のpre_commitファイルが生成される。

.husky/pre-commit
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"

npx lint-staged

.gitディレクトリとpackage.jsonファイルが同じ階層に存在しない場合は、下記のように階層を移動するコマンドを追加する必要がある。

.husky/pre-commit
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"

+ cd next-app  # package.jsonのある階層に移動する
npx lint-staged

ここまでできたら、lint-stagedの設定に移る。

lint-stagedの設定をする Link to this heading

Next.jsにおけるlint-stagedの設定は特殊である。詳細はNext.jsの公式サイトを参照すること。

Configuration: ESLint | Next.js's image

Configuration: ESLint | Next.js

Next.js reports ESLint errors and warnings during builds by default. Learn how to opt-out of this behavior here.

nextjs.org favicon image nextjs.org

要するに、Next.jsにおいてnext lintlint-stagedを共存させる場合は、.lintstagedrc.jsファイルを作成し、そこに設定を記す必要がある。

公式に載っている.lintstagedrc.jsは下記のとおり。

.lintstagedrc.js
const path = require('path')

const buildEslintCommand = (filenames) =>
  `next lint --fix --file ${filenames
    .map((f) => path.relative(process.cwd(), f))
    .join(' --file ')}`

module.exports = {
  '*.{js,jsx,ts,tsx}': [buildEslintCommand],
}

上記のように、module.exportsに、適用するファイルと実行するコマンドのペアを記述する。たとえば、自動修正しないlinterとformatterを実行する場合は、下記のようになる。

.lintstagedrc.js
const path = require('path');

const buildLintCommand = (filenames) =>
  `next lint --file ${filenames
    .map((f) => path.relative(process.cwd(), f))
    .join(' --file ')}`;

const buildFormatCommand = (filenames) =>
  `prettier --check --debug-check ${filenames
    .map((f) => path.relative(process.cwd(), f))
    .join(' ')}`;

module.exports = {
  'app/**/*.{js,jsx,ts,tsx}': [buildLintCommand],
  'pages/**/*.{js,jsx,ts,tsx}': [buildLintCommand],
  '*.{js,jsx,ts,tsx,json,css}': [buildFormatCommand],
};

以上までの設定で、コミット時にlinterとformatterが自動で実行され、通らない場合はコミットできなくなる。

コミットメッセージを自動チェックして統一する Link to this heading

コミットメッセージのフォーマットを統一するため、commitlintを入れる。

commitlint's image

commitlint

Lint commit messages

commitlint.js.org favicon image commitlint.js.org
commitlintとCommitizenを使ってチーム開発におけるコミットメッセージを統一する's image

commitlintとCommitizenを使ってチーム開発におけるコミットメッセージを統一する

zenn.dev favicon image zenn.dev

commitlintを入れる Link to this heading

まず、パッケージをインストールする。

npm install --save-dev @commitlint/{cli,config-conventional}

次に、下記のコマンドを実行してcommitlint.config.jsを作成する。

echo "module.exports = { extends: ['@commitlint/config-conventional'] };" > commitlint.config.js

作成されたcommitlint.config.jsは以下のようになる。

commitlint.config.js
module.exports = {
  extends: ['@commitlint/config-conventional'],
};

上記の代わりに、package.jsonに記述してもよい。

package.json
{
  "commitlint": {
    "extends": [
      "@commitlint/config-conventional"
    ]
  }
}

以上でcommitlintが動作するようになったので、実行されるか確認する。

npx commitlint --from HEAD~1 --to HEAD --verbose

実行されれば、下記のようなログが出力される。

commitlintの実行結果
$ npx commitlint --from HEAD~1 --to HEAD --verbose
⧗   input: build: set up husky and lint-staged pre-commit
✔   found 0 problems, 0 warnings

コミット時にcommitlintを自動実行する Link to this heading

コミット時にcommitlintが自動実行されるように設定する。commitlintcommit-msgフックで実行する。下記のコマンドを実行して、huskyからcommit-msgフックを追加する。

npx husky add .husky/commit-msg  'npx --no -- commitlint --edit ${1}'

これにより、.husky/commit-msgファイルが作成される。

.husky/commit-msg
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"

npx --no -- commitlint --edit ${1}

.gitディレクトリとpackage.jsonが同一階層にない場合は、下記のように階層を移動するコマンドを追加する必要がある。

.husky/commit-msg
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"

+ cd next-app  # package.jsonのある階層に移動する
npx --no -- commitlint --edit ${1}

これで、コミット時にcommitlintが実行されるようになる。

commitlintのルールを変更する Link to this heading

commitlintのルールは、commitlint.config.jsにルールを追記することで上書きできる。デフォルトの設定および上書き方法は、下記公式サイトに記述されている。

commitlint's image

commitlint

Lint commit messages

commitlint.js.org favicon image commitlint.js.org

たとえば、subject-max-length50に変更する場合は、下記のようにルールを追記する。

commitlint.config.js
module.exports = {
  extends: ['@commitlint/config-conventional'],

+ rules: {
+   'subject-max-length': [2, 'always', 50],
+ },
};
commitlint の紹介 - Qiita's image

commitlint の紹介 - Qiita

commitlint というツールをご紹介します。http://marionebl.github.io/commitlintcommitlint とは、Git のコミット規約(commit co…

qiita.com favicon image qiita.com

ルールは、{ルール名}: [{レベル:0|1|2}, '{可否:always|never}', {値}]の形式で記述する。レベルは各数値が下記段階に該当する。

  • 0: 無効
  • 1: 警告
  • 2: エラー

オレオレルールはこんな感じ。

commitlint.config.js
module.exports = {
  extends: ['@commitlint/config-conventional'],

  rules: {
    'type-case': [2, 'always', 'lower-case'],
    'scope-case': [2, 'always', 'lower-case'],
    'subject-max-length': [2, 'always', 50],
    'body-full-stop': [2, 'always', '.'],
    'body-leading-blank': [2, 'always'],
    'body-max-line-length': [2, 'always', 72],
    'body-case': [2, 'always', 'sentence-case'],
    'footer-leading-blank': [2, 'always'],
    'footer-max-line-length': [2, 'always', 72],
  },
};

参考文献・URL Link to this heading

参考文献・URLは適宜記事内に示した。

Licensed under CC BY-NC-SA 4.0
最終更新 2月 24, 2025
Hugo で構築されています。
テーマ StackJimmy によって設計されています。