💻

Next.jsで個人開発をするときのテンプレートを構築する

2023/04/15に公開

はじめに

フロントエンド開発では、eslintprettierといった静的解析ツールや整形ツールの使用はほぼ必須と言って良いでしょう。個人開発でもこれらのライブラリを使用して、ある程度のコード品質は保っておくべきだと思っています。しかし、0からリポジトリを作成して、ライブラリをインストールして、設定して、設定項目を調査して、、、という作業が面倒だと感じたのでテンプレートを作ることにしました(テスティングフレームワークも今後入れたい)。

コードはこちらです。
https://github.com/takumi-pro/next-app-template
スクラップ
https://zenn.dev/takumi/scraps/a1ff6d2522db23

環境

package.json
{
  "name": "next-app-template",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "next lint",
    "prepare": "husky install",
    "lint-staged": "npx lint-staged",
    "commit": "cz"
  },
  "dependencies": {
    "@types/node": "18.15.11",
    "@types/react": "18.0.34",
    "@types/react-dom": "18.0.11",
    "eslint": "8.38.0",
    "eslint-config-next": "13.3.0",
    "next": "13.3.0",
    "react": "18.2.0",
    "react-dom": "18.2.0",
    "typescript": "5.0.4"
  },
  "devDependencies": {
    "@commitlint/cli": "^17.6.0",
    "@commitlint/config-conventional": "^17.6.0",
    "@typescript-eslint/eslint-plugin": "^5.58.0",
    "@typescript-eslint/parser": "^5.58.0",
    "commitizen": "^4.3.0",
    "cz-emoji": "^1.3.2-canary.2",
    "eslint-config-prettier": "^8.8.0",
    "eslint-plugin-react": "^7.32.2",
    "eslint-plugin-react-hooks": "^4.6.0",
    "husky": "^8.0.0",
    "lint-staged": "^13.2.1",
    "prettier": "^2.8.7"
  }
}

初期設定

Next.jsアプリケーションを作成します

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)
git push -u origin main

eslintの設定

eslint自体とその他必要なプラグインなどをインストールします。

npm install -D @typescript-eslint/eslint-plugin @typescript-eslint/parser slint-plugin-react eslint-plugin-react-hooks

設定ファイル.eslintrc.jsonを追加します。

.eslintrc.json

詳細な解説は別記事にまとめる予定です

.eslintrc.json
{
  "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
  }
}

prettierの設定

prettier自体とeslintとの重複ルールを無効化するeslint-config-prettierをインストールします。

npm install -D prettier eslint-config-prettier

prettier設定ファイルを追加します。

.prettierrc.json
{
  "trailingComma": "all",
  "semi": true,
  "singleQuote": true
}

eslintの設定ファイルにprettierを追加します。

.eslintrc.json
 "extends": [
   "eslint:recommended",
   "plugin:@typescript-eslint/recommended",
   "next/core-web-vitals",
+  "prettier"
 ]

VSCodeの設定

ファイルを保存した際に自動でコードが整形されるようにします。
.vscodeディレクトリの下にsettings.jsonファイルを作成してそこにVSCodeの設定を記述します。

settings.json
{
  // ファイルの自動保存を有効化
  // フォーカスが外れた時に保存
  "files.autoSave": "onFocusChange",
  // ファイル保存時に自動的にeslintの問題を修正
  "editor.codeActionsOnSave": {
    "source.fixAll.eslint": true
  },
  // ファイル保存時に自動的にフォーマット
  "editor.formatOnSave": true,
  // VSCodeのデフォルトフォーマッターをprettierに設定
  "editor.defaultFormatter": "esbenp.prettier-vscode"
}

huskyとlint-stagedの設定

huskyはgitフックを簡単に設定するツールです。コミットやプッシュといった特定のアクションを実行する前後に自動的に実行されるスクリプト(gitフック)を設定することができます。今回はeslintprettierをコミット前に実行させます。
lint-stagedはコミット前に実行する対象ファイルをステージングに上がっているファイルに限定されるために使います。

huskyのインストール
サンプルとして.huskyディレクトリにpre-commitファイルが作成されます。

npx husky-init && npm install

lint-stagedのインストール

npm install -D lint-staged

lint-stagedの設定ファイルとして.lintstagedrc.jsonを作成し、ステージングされたファイルに対して実行したいコマンドを記述します。

.lintstaged.json
{
  "*.{js,jsx,ts,tsx}": ["eslint", "prettier --check"]
}

npm scriptを以下のように変更し、huskyをインストールしたときに作成されたpre-commitファイルにコミット前に実行するコマンド(npm run lint-staged)を書き込みます。

package.json
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "next lint",
    "prepare": "husky install",
+   "lint-staged": "npx lint-staged",
  },
pre-commit
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"

npm run lint-staged

これでhuskyとlint-stagedの設定は完了です。

commitlintとcommitizenの設定

ここではコミットメッセージの規約をライブラリで設定し、コミットするときに規約に沿っているかを自動でチェックできるようにします。

commitlintはコミットメッセージが規約に沿っているかをチェックしてくれます。commitizenは開発者が簡単にコミットメッセージのプレフィックスを選択できるようにプロンプトに表示してくれます。

commitlintの導入

commitlintのインストール

npm install -D @commitlint/cli @commitlint/config-conventional

以下のコマンドで設定ファイルを作成します。

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

動作確認としてfoo: barという規約に沿っていない文字列をcommitlintコマンドに渡します。

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

きちんとエラーを出力してくれています。

コミットメッセージ入力後に動作させたいのでcommit-msgフックをhuskyに追加します。

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

.czrcファイルに設定を追加します。

.czrc
{
  "path": "cz-conventional-changelog"
}

次に、commitizenを実行するコマンドをnpm scriptに追加して、適当なファイルをaddしてからnpm run commitを実行するとコミットメッセージを各プレフィックスの中から選択できるようになっています。感動的ですね🥺

package.json
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "next lint",
    "prepare": "husky install",
    "lint-staged": "npx lint-staged",
+   "commit": "cz"
  },
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'

絵文字を使う

コミットメッセージにプレフィックスをつけて整理するだけでもいいと思うのですが、個人的にはもう少し華やかにしたかったのでプレフィックスごとに絵文字を設定しました。

cz-emojiをインストール

npm install -D cz-emoji

.czrcファイルを以下のように編集します。

.czrc
{
- "path": "cz-conventional-changelog"
+ "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": "リソースの移動や名前の変更"
+       }
+     ]
+   }
+ }
}

@commitlint/config-conventionalにないプレフィックスをいくつか設定しているのでcommitlint.config.jsも編集します。

commitlint.config.js
module.exports = {
  extends: ['@commitlint/config-conventional'],
+ rules: {
+   'type-enum': [
+     2,
+     'always',
+     [
+       'feat',
+       'docs',
+       'style',
+       'factor',
+       'perf',
+       'test',
+       'chore',
+       'remove',
+       'move',
+     ],
+   ],
+ },
};

これでコミットメッセージで絵文字を使えるようになりました。
試しにコミットしてみると各プレフィックスに対応した絵文字が表示されていてわかりやすいですね😄

git commit

> next-app-template@0.1.0 lint-staged
> npx lint-staged

✔ Preparing lint-staged...
✔ Running tasks for staged files...
✔ Applying modifications from tasks...
✔ Cleaning up temporary files...
cz-cli@4.3.0, cz-emoji@1.3.2-canary.2

? Select the type of change you're committing: (Use arrow keys or type to search)
❯ feat      ✨  機能追加 
  fix       🐛  バグの修正 
  docs      📚  ドキュメントのみの変更 
  style     🎨  コードの動作に影響しない、見た目だけの変更(スペース、フォーマット、欠落の修正、セミコロンなど) 
  refactor  ♻️  バグの修正や機能の追加ではないコードの変更 
  perf:     🐎  パフォーマンスを向上させるコードの変更 
  test:     ✅  不足しているテストの追加や既存のテストの修正 
(Move up and down to reveal more choices)

githubにもちゃんと反映されていますね。

終わりに

テンプレート構築を進めていてやはりeslintの設定の理解が曖昧だなと感じました。もう少しルールを厳しめにつけたいのでそこは別で調査が必要になりそうです。コミットメッセージに関しては最近業務でもプレフィックスのルールをつけ始めたのですが、急いでいるとつい忘れてしまうこともあるのでそこら辺はライブラリに任せることは良い選択肢なのではと思っています。
これからはこのテンプレートを活用して爆速で開発を進めて行きたいです🔥

参考

https://qiita.com/yukiji/items/5ba9e065ac6ed57d05a4#vs-codeの設定
https://zenn.dev/kimromi/articles/546923b7281dcb
https://zenn.dev/nus3/articles/257d724e24a39b756b5a#10.-lint-staged-%2B-huskyを入れる
https://zenn.dev/horitaka/articles/commit-message-rules
https://qiita.com/manak1/items/e094338fd68e99d20876
https://dev.classmethod.jp/articles/commitizen/

GitHubで編集を提案

Discussion