個人開発におけるNext.jsの最小構成
初期設定
プロジェクトのディレクトリ作成
mkdir next-app-template
cd next-app-template
nextアプリを作成
npm create next-app --typescript
npx: 1個のパッケージを2.137秒でインストールしました。
✔ What is your project named? … .
✔ Would you like to use ESLint with this project? … No / Yes
✔ Would you like to use Tailwind CSS with this project? … No / Yes
✔ Would you like to use `src/` directory with this project? … No / Yes
? Would you like to use experimental `app/` directory with this project✔ Would you like to use experimental `app/` directory with this project? … No / Yes
✔ What import alias would you like configured? … @/*
gitで管理
git init
適宜リポジトリを作成する
作成したら、リモートリポジトリを追加する
git remote add origin [リモートリポジトリurl]
git remote -v
origin [リモートリポジトリurl] (fetch)
origin [リモートリポジトリurl] (push)
pushする
git push -u origin main
ESLintの設定
なるべくルールは厳しくつけたい。
主に以下のようなルールを設定したい。
※既に設定されているなどは関係なくとりあえず列挙する
- import文の順番固定(internal, externalなど)
- マジックナンバー禁止
- シングルクオート
- オブジェクトのキーとプロパティが一致しているときは省略する
- 未使用の変数宣言を禁止
- 未使用の式の使用を禁止
- varの使用を禁止
- useEffectなどの依存配列を適切にする
など、今はそのくらい
importの自動並べ替え
.eslintrc.json
を以下のように編集
{
"extends": ["eslint:recommended", "next/core-web-vitals"],
"plugins": ["import"],
"rules": {
"import/order": [
"error",
{
"groups": ["builtin", "external", "internal"],
"alphabetize": {
"order": "asc"
},
"newlines-between": "always"
}
]
}
}
VSCodeのsettings.jsonを保存時にESLintのルールに沿って修正してくれるように編集
{
// エディタのフォーカスが外れた時に自動保存
"files.autoSave": "onFocusChange",
// 保存した際にESLintのルールに沿って修正
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
}
}
参考
ESLintのenv設定
{
"extends": ["eslint:recommended", "next/core-web-vitals"],
"plugins": ["import"],
"rules": {
"import/order": [
"error",
{
"groups": ["builtin", "external", "internal"],
"alphabetize": {
"order": "asc"
},
"newlines-between": "always"
}
]
},
+ "env" : {
+ "browser": true,
+ "node": true,
+ "es6": true
+ }
}
TypeScriptの設定
{
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
"next/core-web-vitals"
],
"plugins": ["import", "@typescript-eslint"],
"parser": "@typescript-eslint/parser",
"parserOptions": {
"project": "./tsconfig.json"
},
"rules": {
"import/order": [
"error",
{
"groups": ["builtin", "external", "internal"],
"alphabetize": {
"order": "asc"
},
"newlines-between": "always"
}
]
},
"env" : {
"browser": true,
"node": true,
"es6": true
}
}
Prettierの設定
インストール
eslint-config-prettier
はeslint
とprettier
の重複ルールを無効化する
npm install -D prettier eslint-config-prettier
設定ファイル
{
"trailingComma": "all",
"semi": true,
"singleQuote": true
}
{
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
"next/core-web-vitals",
+ "prettier"
],
"plugins": ["import", "@typescript-eslint"],
"parser": "@typescript-eslint/parser",
"parserOptions": {
"project": "./tsconfig.json"
},
"rules": {
"import/order": [
"error",
{
"groups": ["builtin", "external", "internal"],
"alphabetize": {
"order": "asc"
},
"newlines-between": "always"
}
]
},
"env": {
"browser": true,
"node": true,
"es6": true
}
}
Reactの設定(ESLint)
npm install eslint-plugin-react eslint-plugin-react-hooks --save-dev
{
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
+ "plugin:react/recommended",
+ "plugin:react-hooks/recommended",
"next/core-web-vitals",
"prettier"
],
"plugins": [
"import",
"@typescript-eslint"
],
"parser": "@typescript-eslint/parser",
"parserOptions": {
"project": "./tsconfig.json"
},
"rules": {
"import/order": [
"error",
{
"groups": [
"builtin",
"external",
"internal"
],
"alphabetize": {
"order": "asc"
},
"newlines-between": "always"
}
]
},
"env": {
"browser": true,
"node": true,
"es6": true
}
}
ESLint設定ファイル
暫定的ではあるが設定ファイルはこうなった
{
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
"plugin:react/recommended",
"plugin:react-hooks/recommended",
"next/core-web-vitals",
"prettier"
],
"plugins": [
"import",
"@typescript-eslint"
],
"parser": "@typescript-eslint/parser",
"parserOptions": {
"project": "./tsconfig.json"
},
"rules": {
"no-else-return": "error",
"object-shorthand": "error",
"no-magic-numbers": "error",
"camelcase": "error",
"import/order": [
"error",
{
"groups": [
"builtin",
"external",
"internal"
],
"alphabetize": {
"order": "asc"
},
"newlines-between": "always"
}
]
},
"env": {
"browser": true,
"node": true,
"es6": true
}
}
huskyとlint-stagedの設定
huskyインストール
npx husky-init && npm install
.husky
ディレクトリの中にpre-commit
ファイルが作成される。
この中にコミット前に実行したいコマンドを記述する。
ステージングに上がっているものだけESLintとPrettierを走らせたいためlint-staged
をインストール
npm install -D lint-staged
プロジェクトのルートに.lintstagedrc.json
を作成し、ステージングされたファイルに対して実行したいコマンドを記述する。
{
"*.{js,jsx,ts,tsx}": ["eslint", "prettier --check"]
}
npm scriptに追加
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint",
"prepare": "husky install",
+ "lint-staged": "npx lint-staged"
},
.husky/pre-commit
にコマンドを追加
npm run linst-staged
huskyとlint-stagedの設定完了
コミットメッセージ自動チェック
commitlintの導入
commitlint→コミットメッセージをチェック
commitizen→プロンプトからプレフィックスを選択
commitlintのインストール
npm install -D @commitlint/cli @commitlint/config-conventional
設定ファイル追加
echo "module.exports = {extends: ['@commitlint/config-conventional']}" > commitlint.config.js
動作確認
echo 'foo: bar' | commitlint
⧗ input: foo: bar
✖ type must be one of [build, chore, ci, docs, feat, fix, perf, refactor, revert, style, test] [type-enum]
✖ found 1 problems, 0 warnings
ⓘ Get help: https://github.com/conventional-changelog/commitlint/#what-is-commitlint
huskyにcommit-msgフックを追加する
npx husky add .husky/commit-msg 'npx --no -- commitlint --edit ${1}'
commitizenの導入
インストール
npm install -D commitizen
リポジトリをcommitizenに対応させる
npx commitizen init cz-conventional-changelog --save-dev --save-exact
設定ファイル追加
{
"path": "cz-conventional-changelog"
}
npm scriptに追加
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint",
"prepare": "husky install",
"lint-staged": "npx lint-staged",
+ "commit": "cz"
},
適当なファイルをaddして動作確認
npm run commit
> next-app-template@0.1.0 commit
> cz
cz-cli@4.3.0, cz-conventional-changelog@3.3.0
? Select the type of change that you're committing: (Use arrow keys)
❯ feat: A new feature
fix: A bug fix
docs: Documentation only changes
style: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc)
refactor: A code change that neither fixes a bug nor adds a feature
perf: A code change that improves performance
test: Adding missing tests or correcting existing tests
(Move up and down to reveal more choices)
prepare-commit-msg
フックでコミット時にプロンプト表示
npx husky add .husky/prepare-commit-msg 'exec < /dev/tty && node_modules/.bin/cz --hook || true'
commitizenの追加設定
commitizenの日本語化
cz-conventional-changelog-ja
のインストール
npm install -D cz-conventional-changelog-ja
設定ファイル変更
{
"path": "cz-conventional-changelog-ja"
}
commitizenの選択項目設定
cz-customizable
のインストール
npm install -D cz-customizable
設定ファイル追加
module.exports = {
skipQuestions: ['scope', 'body', 'breaking', 'footer'],
};
複数のadapterが使用できない問題
.czrc
ファイルに複数のadapterを設定したかったがどうやらまだ対応していない?
.cz-config.js
に以下を記述
module.exports = {
types: [
{
value: '🌟 feat',
name: 'feat: 機能追加',
title: 'Features',
},
{
value: '🔧 fix',
name: 'fix: バグの修正',
title: 'Bug Fixes',
},
{
value: '🗒 docs',
name: 'docs: ドキュメントのみの変更',
title: 'Documentation',
},
{
value: '🎨 style',
name: 'style: コードの動作に影響しない、見た目だけの変更(スペース、フォーマット、欠落の修正、セミコロンなど)',
title: 'Styles',
},
{
value: '♻️ refactor',
name: 'refactor: バグの修正や機能の追加ではないコードの変更',
title: 'Code Refactoring',
},
{
value: '⏫ perf',
name: 'perf: パフォーマンスを向上させるコードの変更',
title: 'Performance',
},
{
value: '🧪 test',
name: 'test: 不足しているテストの追加や既存のテストの修正',
title: 'Tests',
},
{
value: '🐧 chore',
name: 'chore: ビルドプロセスやドキュメント生成などの補助ツールやライブラリの変更',
title: 'Chores',
},
],
messages: {
type: 'コミットする変更タイプを選択してください:\n',
subject: 'コミット内容について入力してください:\n',
confirmCommit: 'こちらの内容でコミットを実行してよろしいですか?:\n',
},
skipQuestions: ['scope', 'body', 'breaking', 'footer'],
};
.czrc
を変更
{
- "path": "cz-conventional-changelog-ja"
+ "path": "cz-customizable"
}
最終的なcommitizenとcommitlintの設定
追加したライブラリ
- @commitlint/cli
- @commitlint/config-convectional
- commitizen
- cz-emoji
.czrc
設定ファイル
{
"path": "cz-emoji",
"config": {
"cz-emoji": {
"subjectMaxLength": 72,
"skipQuestions": [
"scope",
"body",
"breaking",
"footer"
],
"types": [
{
"emoji": "✨",
"name": "feat",
"code": "feat: :sparkles:",
"description": "機能追加"
},
{
"emoji": "🐛",
"name": "fix",
"code": "fix: :bug:",
"description": "バグの修正"
},
{
"emoji": "📚",
"name": "docs",
"code": "docs: :books:",
"description": "ドキュメントのみの変更"
},
{
"emoji": "🎨",
"name": "style",
"code": "style: :art:",
"description": "コードの動作に影響しない、見た目だけの変更(スペース、フォーマット、欠落の修正、セミコロンなど)"
},
{
"emoji": "♻️",
"name": "refactor",
"code": "refactor: :recycle:",
"description": "バグの修正や機能の追加ではないコードの変更"
},
{
"emoji": "🐎",
"name": "perf:",
"code": "perf: :horse:",
"description": "パフォーマンスを向上させるコードの変更"
},
{
"emoji": "✅",
"name": "test: ",
"code": "test: :white_check_mark:",
"description": "不足しているテストの追加や既存のテストの修正"
},
{
"emoji": "👷♂️",
"name": "chore",
"code": "chore: :construction_worker:",
"description": "ビルドプロセスやドキュメント生成などの補助ツールやライブラリの変更"
},
{
"emoji": "🗑",
"name": "remove",
"code": "remove: :wastebasket:",
"description": "コードの削除"
},
{
"emoji": "🚚",
"name": "move",
"code": "move: :truck:",
"description": "リソースの移動や名前の変更"
}
]
}
}
}
`skipQuestions`に設定できるもの
chatGPTに聞いてみた
commitlint設定ファイル
module.exports = {
extends: ['@commitlint/config-conventional'],
rules: {
'type-enum': [
2,
'always',
[
'feat',
'docs',
'style',
'factor',
'perf',
'test',
'chore',
'remove',
'move',
],
],
},
};