Next.js 14 + TypeScript + Tailwind + ESLint + Prettier 環境構築手順
Next.js プロジェクトにおけるベーシックな環境として TypeScript、Tailwind、ESLint、Prettier を導入する手順をまとめます。
また、Next.js は App Router を採用します。
前提
- Node.js 20.10.0
- pnpm 8.10.2
Next.js インストール
公式のコマンド通りに Next.js のプロジェクトをセットアップします。
pnpm create next-app
対話式で以下のように回答。
? What is your project named? › my-app
# プロジェクト名を入力
? Would you like to use TypeScript? › No / Yes
# Yes を選択
? Would you like to use ESLint? › No / Yes
# Yes を選択
? Would you like to use Tailwind CSS? › No / Yes
# Yes を選択
? Would you like to use `src/` directory? › No / Yes
# 好みで選択(個人的に最近は No にしている)
? Would you like to use App Router? (recommended) … No / Yes
# Yes を選択
? Would you like to customize the default import alias (@/*)? … No / Yes
# No を選択
セットアップが完了すると、以下のディレクトリ構成でプロジェクトが作成されます。
.
├── public
│ ├── next.svg
│ └── vercel.svg
├── src
│ └── app
│ ├── favicon.ico
│ ├── globals.css
│ ├── layout.tsx
│ └── page.tsx
├── .eslintrc.json
├── .gitignore
├── next-env.d.ts
├── next.config.js
├── package.json
├── pnpm-lock.yaml
├── postcss.config.js
├── README.md
├── tailwind.config.ts
└── tsconfig.json
表示確認し、問題なければここで git push
しておきます。
pnpm dev
SSG エクスポート設定
SSG によるエクスポートをおこなう場合は、next.config.js
にエクスポート設定を追加します。v13
までの next export
コマンドは v14
では廃止されています。
/** @type {import('next').NextConfig} */
const nextConfig = {
+ output: 'export',
+ distDir: 'dist'
}
module.exports = nextConfig
これで next build
を実行すると dist
ディレクトリに静的ファイルが出力されますので、.gitignore
にも /dist/
を追加しておきます。
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.js
.yarn/install-state.gz
# testing
/coverage
# next.js
/.next/
/out/
+ /dist/
# production
/build
# misc
.DS_Store
*.pem
# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# local env files
.env*.local
# vercel
.vercel
# typescript
*.tsbuildinfo
next-env.d.ts
パスエイリアスの設定
プロジェクト作成時の対話式コマンドで import
のパスエイリアスを設定済ですが、ドキュメントルート直下のデータを参照するためのパスエイリアスも追加しておきます。
また、target
の値を esnext
に変更しておきます。
{
"compilerOptions": {
- "target": "es5",
+ "target": "esnext",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "bundler",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"incremental": true,
"plugins": [
{
"name": "next"
}
],
"paths": {
"@/*": ["./src/*"]
+ "@@/*": ["./*"]
}
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
"exclude": ["node_modules"]
}
これにより ESModules で下記のような記述でのインポートができるようになります。
import buttonA from '@/components/buttonA'
import config from '@@/package.json'
.node-version の追加
自分の環境では nodenv を利用しているので、利用中の Node バージョンに合わせて .node-version
ファイルを作成します。
node -v
v20.10.0
nodenv local 20.10.0
.editorconfig の追加
.editorconfig
を追加します。
# http://editorconfig.org
root = true
[*]
charset = utf-8
end_of_line = lf
indent_style = space
indent_size = 2
trim_trailing_whitespace = true
insert_final_newline = true
[*.{md,markdown}]
trim_trailing_whitespace = false
Prettier
コードフォーマットの環境を整えるために、以下のコマンドで Prettier と関連プラグインをインストールします。
pnpm add -D prettier prettier-plugin-organize-imports
Prettier の設定ファイル .prettierrc
を以下の内容をでプロジェクトのルートに配置します。
{
"trailingComma": "all",
"tabWidth": 2,
"useTabs": false,
"semi": false,
"singleQuote": true,
"jsxSingleQuote": false,
"arrowParens": "always",
"printWidth": 80,
"bracketSpacing": true,
"plugins": ["prettier-plugin-organize-imports"],
"overrides": [
{
"files": "*.html",
"options": {
"printWidth": 360
}
},
{
"files": ["*.css", "*.scss"],
"options": {
"singleQuote": false
}
}
]
}
フォーマットの対象外を定義した .prettierignore
も合わせて配置します。
node_modules/
.next/
.nuxt/
.astro/
build/
dist/
out/
public/
package-lock.json
yarn.lock
pnpm-lock.yaml
next.config.js
VS Code 設定
ファイル保存時に Prettier が動作するように、以下の内容で .vscode/settings.json
をドキュメントルートに作成します。ついでに import
文の補完処理も追記しておきます。
{
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.formatOnSave": true,
"editor.formatOnPaste": true,
"editor.codeActionsOnSave": {
"source.addMissingImports": "explicit",
},
"javascript.preferences.importModuleSpecifier": "non-relative",
"typescript.preferences.importModuleSpecifier": "non-relative",
}
ESLint
ESLint では以下のパッケージをインストールして利用します。
過去には eslint-config-standard-with-typescript
をはじめ、複数の共有設定やプラグインを導入して細かいルールを設定していましたが、導入や保守に手間をかけたくはないので、Next.js が採用している next/core-web-vitals
をベースに以下のプラグインをインストールすることにしました。
-
@typescript-eslint/eslint-plugin
- TypeScript の推奨ルールを提供するプラグイン
-
@typescript-eslint/parser
- TypeScript を解析するためのパーサ
-
eslint-plugin-tailwindcss
- Tailwind CSS のベストプラクティスを提供するプラグインで、クラス名のソートや矛盾するクラスの解消、複数クラスの短縮化などをおこなってくれます
-
eslint-config-prettier
- Prettier と ESLint を併用するための競合ルールを解消する共有設定です
pnpm add -D @typescript-eslint/parser @typescript-eslint/eslint-plugin eslint-plugin-tailwindcss eslint-config-prettier
以下の内容で .eslintrc.json
を更新します。
{
"extends": [
"next/core-web-vitals",
"plugin:@typescript-eslint/recommended",
"plugin:tailwindcss/recommended",
"prettier"
],
"parser": "@typescript-eslint/parser",
"plugins": ["@typescript-eslint"],
"rules": {
"@typescript-eslint/consistent-type-imports": [
"error",
{
"prefer": "type-imports",
"fixStyle": "separate-type-imports"
}
],
"@typescript-eslint/no-unused-vars": [
"warn",
{
"vars": "all",
"varsIgnorePattern": "^_",
"args": "after-used",
"argsIgnorePattern": "^_"
}
],
"object-shorthand": "error",
"tailwindcss/no-custom-classname": "off",
"react/jsx-curly-brace-presence": "error",
"react/self-closing-comp": [
"error",
{
"component": true,
"html": false
}
],
"@next/next/no-img-element": "off",
}
}
.eslintignore
も追加します。こちらも .prettierrc
同様、パースエラーによる不具合の出る可能性のある設定系のファイルは対象外に含めています。
node_modules/
.next/
.nuxt/
.astro/
build/
dist/
out/
public/
package-lock.json
yarn.lock
pnpm-lock.yaml
vite.config.ts
next.config.js
tsconfig.json
src/env.d.ts
*.cjs
*.mjs
VS Code 追加設定
VS Code の設定に ESLint 関連の設定を追加します。
{
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.formatOnSave": true,
"editor.formatOnPaste": true,
"editor.codeActionsOnSave": {
"source.addMissingImports": "explicit",
+ "source.fixAll.eslint": "explicit",
},
"javascript.preferences.importModuleSpecifier": "non-relative",
"typescript.preferences.importModuleSpecifier": "non-relative",
+ "eslint.validate": [
+ "html",
+ "javascript",
+ "javascriptreact",
+ "typescript",
+ "typescriptreact"
+ ],
}
フォーマットコマンドの追加
npm-run-all
パッケージをインストールし、npm scripts から実行できるフォーマットコマンドを追加します。
pnpm add -D npm-run-all
{
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
- "lint": "next lint"
+ "lint": "run-p -l -c --aggregate-output lint:*",
+ "lint:eslint": "eslint .",
+ "lint:prettier": "prettier --check .",
+ "fix": "run-s fix:prettier fix:eslint",
+ "fix:eslint": "npm run lint:eslint -- --fix",
+ "fix:prettier": "npm run lint:prettier -- --write",
},
}
上記コマンドは以下の記事を参考にしました。
記事で言及されている通り、ポイントは以下となります。
- フォーマットの対象ファイルは
.eslintignore
と.prettierignore
で管理し、npm scripts には記述しない -
npm-run-all
を利用して処理のための記述をシンプルにする -
fix
は Prettier → ESLint の順に順次実行させる
Husky + lint-staged
Prettier と VS Code の設定により、コーディング中に自動フォーマットが行われるようになっていますが、Husky と lint-staged を導入してコミット前に自動フォーマットと検知・修正をおこなうようにします。
pnpm add -D husky lint-staged
Husky のインストール後のセットアップ手順は公式サイトも参考にしてください。
以下のコマンドで Husky による Git フックを有効化します。フックが有効化されるとドキュメントルートに .husky
ディレクトリが作られます。
npx husky install
npm scripts に prepare
コマンドを追加します。これによりプロジェクトをインストールした開発者が意識しなくても Husky を利用する準備が自動的におこなわれます。
npm pkg set scripts.prepare="husky install"
コミット前に lint-staged を実行する Git フックを husky
コマンドから追加します。
npx husky add .husky/pre-commit "npx lint-staged"
package.json
に lint-staged でおこなう処理を追加します。
{
...
"devDependencies": {
...
},
+ "lint-staged": {
+ "src/**/*.{js,jsx,ts,tsx}": [
+ "eslint --fix",
+ "prettier --write"
+ ]
+ }
}
ここまでの設定を完了してからファイルのコミットを実行すると、ステージされているファイルに対して pre-commit
で定義した処理が自動実行されます。ここでは pre-commit
に npx lint-staged
の処理を定義しているため、ステージングされたファイルの拡張子に応じて package.json
に記述した lint-staged
の処理、すなわち ESLint と Prettier が実行されます。
Discussion