最近、Next.js、TypeScript、Tailwind CSSを使って技術ブログを立ち上げました。(まだあまり更新は進んでいませんが…)
このプロジェクトを通じて構築した開発環境がわりと快適だったので、誰かの参考になるかもしれないと記事を書いてみることにしました。
できる限りわかりやすく詳細な説明を心がけましたが、その結果、記事のボリュームが大きくなってしまいました。長文ですが、興味のある方はぜひ読んでみてください🙏
https://github.com/ynoki10/next-ts-tailwind-starter
また、この記事内で紹介した内容をセットアップしたリポジトリを公開しています。
Next.jsのボイラープレートとして活用可能ですので、興味のある方はぜひ覗いてみてください。
内容に関してはできる限り調査して情報まとめたつもりですが、もし間違いがあった場合はコメントで教えていただけると幸いです。
アドバイスやご感想のコメントもお待ちしております!
ツール名 | バージョン |
---|---|
Visual Studio Code | 1.85.2 |
Node.js | 20.10.0 |
npm | 10.2.3 |
※ npm は適宜 yarn や pnpm に読みかえていただいても問題ありません。
パッケージ名 | バージョン |
---|---|
next | 14.1.0 |
typescript | 5.3.3 |
tailwindcss | 3.4.1 |
eslint | 8.56.0 |
husky | 9.0.6 |
lint-staged | 15.2.0 |
markuplint | 3.15.0 |
prettier | 3.2.4 |
secretlint | 8.1.0 |
@typescript-eslint/eslint-plugin | 6.19.1 |
@typescript-eslint/parser | 6.19.1 |
eslint-config-prettier | 9.1.0 |
eslint-plugin-tailwindcss | 3.14.1 |
eslint-plugin-unused-imports | 3.0.0 |
※ Next.jsはApp Routerで進めていますが、当記事の内容はPages Routerでもそのまま適用できるようになっていると思います。
まずはcreate-next-app を利用して新規プロジェクトを作成します。
https://nextjs.org/docs/app/api-reference/create-next-app
npx create-next-app@latest
対話形式の質問に答えることで、回答に応じたプロジェクトを作成してくれます。
What is your project named?[プロジェクト名]Would you like to use TypeScript? YesWould you like to use ESLint? YesWould you like to use Tailwind CSS? YesWould you like to use`src/` directory? NoWould you like to use App Router?(recommended) YesWould you like to customize the defaultimportalias(@/*)? No
ここでは全てデフォルトの設定を利用します。
すべての項目に答えると必要なパッケージが読み込まれ、プロジェクトが作成されます。
続いてTypeScriptに関する設定を行います。create-next-app
で作成されたデフォルトのtsconfig.json
でもすでに十分な印象はありますが、ここでは少しだけ設定を追加しておきます。
{"compilerOptions":{"lib":["dom","dom.iterable","esnext"],-"allowJs":true,+"allowJs":false,"skipLibCheck":true,"strict":true,"noEmit":true,"esModuleInterop":true,"module":"esnext","moduleResolution":"bundler","resolveJsonModule":true,"isolatedModules":true,"jsx":"preserve","incremental":true,+"forceConsistentCasingInFileNames":true,+"noImplicitReturns":true,+"noUncheckedIndexedAccess":true,"plugins":[{"name":"next"}],"paths":{"@/*":["./*"]}},"include":["next-env.d.ts","**/*.ts","**/*.tsx",".next/types/**/*.ts"],"exclude":["node_modules"]}
追加・変更した内容は次の通りです。
型の恩恵に預かりたいのでJSは使用しない方針でいきます。false
にすることで.js
.jsx
をコンパイル対象外とすることができます。
ファイル名の大文字小文字を区別します。
https://www.typescriptlang.org/tsconfig#forceConsistentCasingInFileNames
戻り値がvoid
以外の関数において、すべての条件分岐で戻り値を返すよう強制します。
https://typescriptbook.jp/reference/tsconfig/noimplicitreturns
インデックス型のプロパティや配列要素を参照したときundefined
のチェックを必須にします。
https://typescriptbook.jp/reference/tsconfig/nouncheckedindexedaccess
https://azukiazusa.dev/blog/typescript-no-unchecked-indexed-access/
ここで追加した設定以外にも「これ入れとくといいよ!」というものがあればコメントください!
Prettierを導入しコードの自動整形を行います。
コードをきれいに保っておくためにも必ず入れておきたいですね。
https://prettier.io/
まずは Prettier 本体をインストールします。
npm i-D prettier
.prettierrc.json
というファイル名で設定ファイルを作成します。
設定はそれぞれの好みですが、私はこんな感じにしています。
{"printWidth":120,"tabWidth":2,"semi":true,"trailingComma":"all","singleQuote":true,"arrowParens":"always"}
https://zenn.dev/rescuenow/articles/c07dd571dfe10f
Prettierはプロジェクトの.gitignore
で指定されたファイルを自動的にフォーマット対象外とします。
追加で除外したいファイルがある場合は.prettierignore
というファイルで指定が可能です。
https://prettier.io/docs/en/ignore.html
ここではpackage-lock.json
を指定しておきます。(yarn
やpnpm
を利用している場合はそれぞれの lock ファイルを指定してください)
/package-lock.json
npm-scriptsにフォーマットのためのコマンドを追加しておきましょう。
https://ics.media/entry/12226/
"scripts":{ ...+"prettier":"prettier --write ."},
この状態で
npm run prettier
を実行すると、プロジェクト内の全ての対象ファイルをフォーマットしてくれます。
VSCodeにPrettierの拡張機能を入れることでファイル保存時に自動フォーマットが可能になります。esbenp.prettier-vscode
をインストールして有効化してください。
https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode
さらに.vscode/settings.json
を作成して、次のように記述します。
{"editor.defaultFormatter":"esbenp.prettier-vscode",// Prettierをフォーマッターとして設定"editor.formatOnSave":true// ファイル保存時にフォーマットする}
これにより、ファイル保存時に自動でPrettierによるフォーマットが実行されます。
自動フォーマットする拡張子を限定したい場合は次のように記述できます。
{"editor.defaultFormatter":"esbenp.prettier-vscode","editor.formatOnSave":false,"[javascript]":{"editor.formatOnSave":true},"[json]":{"editor.formatOnSave":true},"[typescript]":{"editor.formatOnSave":true},"[typescriptreact]":{"editor.formatOnSave":true}}
こうすると.js
.json
.ts
.tsx
の保存時のみ自動フォーマットが実行されます。
または全ファイルに対して"editor.formatOnSave": true
とした上で、無効化したい拡張子に"editor.formatOnSave": false
を指定するというブラックリスト方式でもOKです。
TypeScript(JavaScript)の構文チェックのためESLintの設定を行います。
コードの品質を高く保つためにもここはできるだけ丁寧に設定しておきます。
https://eslint.org/
まずはcreate-next-app
で作成されたpackage.json
と.eslintrc.json
を見てみましょう。
{"scripts":{ ..."lint":"next lint"}, ..."devDependencies":{ ..."eslint":"^8","eslint-config-next":"14.1.0"}}
{"extends":"next/core-web-vitals"}
すでに
lint
)の設定eslint
とeslint-config-next
のインストール.eslintrc.json
)のextends
にnext/core-web-vitals
を指定までセットアップされていることが分かります。
ちなみにnext/core-web-vitals
は主にReactやNext.js独自のルールを適用するものとなっています。(詳細について知りたい方はNext.jsの公式ドキュメントを参照してください。)
ただ、正直なところこれだけでは全く安心して開発ができません。
そのため、これからプラグインや設定を追加していきます。
next/core-web-vitals
の内部では最終的に次の4つのプラグインをインポートしています。
eslint-plugin-react
eslint-plugin-react-hooks
(extends経由で追加)eslint-plugin-jsx-a11y
eslint-plugin-import
そして、次の3つのプラグインの推奨ルールセット(recommended
)を適用しています。
eslint-plugin-react
eslint-plugin-react-hooks
eslint-plugin-next
深掘りしていくと少しややこしいですが、ESLintのpluginsとextendsの関係性を理解した上でeslint-config-nextのリポジトリを眺めてみると仕組みがおおよそ把握できると思います。
next lint
はデフォルトではpages/
app/
components/
lib/
src/
のみをLintの対象とします。
これ以外のディレクトリを使用したり、逆にLintの対象ディレクトリを制限したい場合はnext.config.js
にて設定が必要です。
例)ESLintの対象をapp/
components/
utils/
hooks/
の4ディレクトリとする
const nextConfig={eslint:{dirs:["app","components","utils","hooks"],},};module.exports= nextConfig;
https://nextjs.org/docs/pages/building-your-application/configuring/eslint#linting-custom-directories-and-files
https://www.mizdra.net/entry/2023/01/13/013855
next/core-web-vitals
にはJavaScriptの基本的な構文に関するルールが含まれていません。
そこで、まずはESLint本体の推奨ルールセット(eslint:recommended
)を適用しましょう。
.eslintrc.json
を次のように更新してください。
{-"extends":"next/core-web-vitals"+"extends":["eslint:recommended","next/core-web-vitals"]}
これにより JavaScript の基本的な構文エラーが検出できるようになります。
https://eslint.org/docs/latest/rules/
https://www.tam-tam.co.jp/tipsnote/javascript/post11934.html
続いてTypeScript用のESLintルールtypescript-eslint を追加しましょう。
https://typescript-eslint.io/
まずは次の2パッケージをインストールしてください。
npm i-D @typescript-eslint/eslint-plugin @typescript-eslint/parser
パッケージ名 | 概要 |
---|---|
@typescript-eslint/parser | TypeScriptの構文を解析するパーサー |
@typescript-eslint/eslint-plugin | Typescript用のESLintプラグイン (推奨ルールセットもここに含まれている) |
そして.eslintrc.json
を次のように更新します。
{"extends":["eslint:recommended",+"plugin:@typescript-eslint/recommended-type-checked","next/core-web-vitals"],+"parser":"@typescript-eslint/parser",+"parserOptions":{+"project":"./tsconfig.json"}}
追加した内容は以下の通りです。
typescript-eslint
には次の6つのルールセットがあります。
型情報を利用しない | 型情報を利用する | |
---|---|---|
厳格なルール | strict | strict-type-checked |
推奨ルール | recommended | recommended-type-checked |
構文を統一するルール | stylistic | stylistic-type-checked |
これだけではどれを使えばよいか迷ってしまいますね。
完全に私感ですが、これらのルールについて調べた結果として、私は次のような印象を抱きました。
そのため、ここではrecommended-type-chekced
(推奨&型情報を利用する)のみを使用しています。
全てのルールを詳しく確認したわけではないので間違っている部分があるかもしれません。
誤りに気づいた方はコメントくださると嬉しいです。
https://typescript-eslint.io/linting/configs/
https://zenn.dev/cybozu_frontend/articles/ts-eslint-v6-guide#v6-からのルールセット
https://zenn.dev/nekoya/articles/34e7002b8f164d
TypeScript の構文を解析するためのパーサーを指定しています。
extendsでrecommended-type-chekced
(型情報を利用するルール)を指定すると、このparserOptions.project
の指定が必須となります。
ここでプロジェクトのtsconfig.json
のパスを指定することで、ESLintにプロジェクトのTypeScript設定を伝えることができます。
ちなみにパスではなくtrue
を渡すと自動的に一番近いtsconfig.json
を探してくれるそうです。(ここではわかりやすさのため明示的にパスを指定しました)
https://typescript-eslint.io/packages/parser/#project
続いて、コード内で使用していないimportの自動削除をしてくれるプラグインeslint-plugin-unused-imports を追加します。
未使用のimport文を手動で消す手間が省けるため、入れておくとかなり便利です。
https://github.com/sweepline/eslint-plugin-unused-imports
こちらはパッケージをインストールしてplugins
とrules
に追加するだけで設定完了です。
npm i-D eslint-plugin-unused-imports
{ ...+"plugins":["unused-imports"],+"rules":{+"unused-imports/no-unused-imports":"error"+}}
続いてimportの順番を自動で整列してもらうように設定を追加していきます。
これはeslint-plugin-import
のimport/order を使って設定ができます。
eslint-plugin-import
はeslint-config-next
にすでに含まれているため、ここではパッケージのインストールやplugins
の指定は不要です(明示的にインストール&指定しても問題はありません)。
並べ方はそれぞれの好みやディレクトリ構成によりますが、私はとりあえず次のような設定としています。
"rules":{ ...+"import/order":[+"error",+{+"groups":["builtin","external","internal","parent","sibling","index","object","type"],+"newlines-between":"always",+"pathGroupsExcludedImportTypes":["builtin"],+"pathGroups":[+{+"pattern":"@/components/**",+"group":"internal",+"position":"before"+}+],+"alphabetize":{+"order":"asc"+}+}+]}
こだわりたい方は公式ドキュメントや以下の記事などを参考にしてみてください。
https://zenn.dev/knowledgework/articles/0994f518015c04#importの自動整列(import%2Forder)
https://zenn.dev/riemonyamada/articles/02e8c172e1eeb1
JSXコンポーネントのPropsの順番も自動でソートしてもらいましょう。
これはeslint-plugin-react
のjsx-sort-props を有効にするだけで可能です。
eslint-plugin-react
はeslint-config-next
に含まれているため、ここでもパッケージのインストールやplugins
の指定は不要です。
"rules":{ ...+"react/jsx-sort-props":"error",}
これにはビルドサイズを減らす効果もあるようです。コードもきれいになって一石二鳥ですね 🙌
https://zenn.dev/team_zenn/articles/sorting-props-reduces-gzip-size
Tailwind CSSを使っていて「クラス名の順番がバラバラでわかりにくい」「pr-1 pl-1
とpx-1
のような書き方が混在していて気持ち悪い」などと思ったことはないでしょうか?
私はあります。
そんな悩みを解決するために、プラグインeslint-plugin-tailwindcss を追加しましょう。
https://github.com/francoismassart/eslint-plugin-tailwindcss
このプラグインによって次のようなことが可能になります。(詳しくはドキュメントを参照)
-top-[5px]
をtop-[-5px]
にする)pr-1 pl-1
をpx-1
にする)p-2 p-3
のような重複に警告を出す)まずはパッケージをインストールしてください。
npm i-D eslint-plugin-tailwindcss
そして.eslintrc.json
に推奨ルールをセットすれば設定完了です。
"extends":["eslint:recommended","plugin:@typescript-eslint/recommended-type-checked","next/core-web-vitals",+"plugin:tailwindcss/recommended"],
Tailwind CSS公式のPrettierプラグイン(prettier-plugin-tailwindcss)も存在するのですが、こちらはクラス順のソートにしか対応していません。そのためここでは機能が充実しているESLintのプラグインを採用しています。
ESLintでフォーマットに関するルールを設定していると、Prettierとバッティングしてしまう可能性があります。そんなバッティングを回避するためのルールeslint-config-prettier を追加します。
https://github.com/prettier/eslint-config-prettier
まずはパッケージをインストールしてください。
npm i-D eslint-config-prettier
そして.eslintrc.json
のextends
にこの設定を追加すればOKです。
eslint-config-prettier
は「Prettierと衝突する可能性のある全てのESLlintルールをオフにする」という設定なので、extendsの一番最後に指定するのがよいでしょう。(extends
では後に指定したルールが前のルールを上書きします)
"extends":["eslint:recommended","plugin:@typescript-eslint/recommended-type-checked","next/core-web-vitals","plugin:tailwindcss/recommended",+"prettier"],
ここまでplugins
に@typescript-eslint
やtailwindcss
、import
を指定していないことに疑問を持った方がいるかも知れません。
実を言うとこれらはplugins
に書いても書かなくても同じように動作します。
@typescript-eslint
やtailwindcss
は extends で適用しているため指定不要import
はnext/core-web-vitals
内で読み込まれているため指定不要分かりやすさのためこれらを明示的に指定しても良いですが、今回はextends
で使用しているプラグインはplugins
に指定しない
という方針で記述しました。
詳しく知りたい方はESLintの extends と plugins について調べてみてください。
https://blog.ojisan.io/eslint-plugin-and-extend/
https://zenn.dev/kimromi/articles/b7cf98005f3193
npm-scriptsにESLintのfix用コマンドを追加します。
"scripts":{ ..."lint":"next lint",+"lint:fix":"next lint --fix", ...},
この状態で
npm run lint:fix
を実行すると、next lint
の対象ファイルをチェックした上で、可能な箇所は自動修正してくれます。
VSCodeにESLintの拡張機能を追加しましょう。これによりエディタ上にESLintの警告を出したり、ファイル保存時の自動修正を行うことが可能になります。
dbaeumer.vscode-eslint
をインストールして有効化してください。
https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint
これでエディタにESLintのエラーが表示されるようになります。
さらに.vscode/settings.json
を更新します。
{+"editor.codeActionsOnSave":{+"source.fixAll.eslint":"explicit"// ファイル保存時にESLintの自動修正を実行する+}, ...}
これにより、ファイル保存時にESLintによる自動修正が行われるようになります。
続いてHTMLの構文チェックをするためMarkuplint を導入していきましょう。
アクセシビリティ向上のためにもぜひ入れておくことをおすすめします。
https://markuplint.dev/ja/
導入用のコマンドがあるのでそちらを使用します。
npx markuplint--init
対話形式の質問に答えることで、設定ファイルの作成から必要なパッケージのインストールまでを自動実行してくれます。
✔ Whichdo you use template engines? · React(JSX)✔ May Iinstall them automatically?(y/N) ·true✔ Do you customize rules?(y/N) ·false✔ Does itimport the recommended config?(y/N) ·true
以上の内容で回答を進めると.markuplintrc
という設定ファイルが作成され、さらに次の3パッケージがインストールされます。
パッケージ名 | 概要 |
---|---|
markuplint | Markuplint本体 |
@markuplint/jsx-parser | JSX用のパーサプラグイン |
@markuplint/react-spec | React用のスペックプラグイン(React特有の属性を解釈してくれる) |
作成された.markuplintrc
を確認してみましょう。
{"specs":{"\\.[jt]sx?$":"@markuplint/react-spec"},"parser":{"\\.[jt]sx?$":"@markuplint/jsx-parser"},"extends":["markuplint:recommended"]}
インストールしたパーサーとスペックプラグインが指定され、推奨プリセットルールも設定済みとなっていることが分かります。
このファイルに少しだけ修正を加えます。
{ ..."extends":[-"markuplint:recommended"+"markuplint:recommended-react"// recommended + React用の追加ルール]}
extends
の設定をmarkuplint:recommended-react
(React用の推奨プリセット)に変更しました。これは「基本プリセットを全て読み込んだ上で React 用のルールを追加する」という設定[1]です。
Markuplintのドキュメントには一度目を通しておくのがおすすめです。それほどたくさんルールがあるわけではないので、わりとサクッと読めます。
Markuplintのプリテンダーという機能を利用すると、コンポーネントごとに対応するHTML要素を定義することができます。
できる限り多くのコンポーネントにプリテンダーを設定するのが望ましいですが、まずは頻出コンポーネントから優先的に設定しておくだけでも効果が期待できそうです。
私自身まだきちんと使えていませんが、Nextの<Image>
をimg要素、<Link>
をa要素に紐付ける設定をプロジェクトにデフォルトで入れておくのも良いかもしれません。
https://markuplint.dev/ja/docs/guides/besides-html#pretenders
Markuplintについても npm-scripts を追加しておきます。
"scripts":{ ...+"markuplint":"markuplint \"./**/*.tsx\"",},
この状態で
npm run markuplint
を実行すると、プロジェクト内の.tsx
ファイルに対してマークアップの構文チェックを行ってくれます。[2]
MarkuplintにもVSCode拡張機能があるので入れておきましょう。
これを入れておくとエディタ上で Markuplint の警告が表示されるようになります。
yusukehirao.vscode-markuplint
をインストールして有効化してください。
https://marketplace.visualstudio.com/items?itemName=yusukehirao.vscode-markuplint
さらに.vscode/settings.json
を更新します。
{ ...+"markuplint.enable":true// Markuplintを有効化する}
これによってエディタ上で Markuplint のエラーを確認できるようになります。
続いてSecretlintの導入を進めていきましょう。
Secretlint はAPIトークンや秘密鍵など、リポジトリにコミットしてはいけないデータがファイルに含まれていないかをチェックするツールです。
https://github.com/secretlint/secretlint
https://efcl.info/2020/03/24/secretlint/
「APIへのアクセストークンを誤って公開してしまった」というような事故を防ぐためにもぜひ導入しておきましょう。(もちろんこれを入れておけば絶対安心、というものではないのでご注意ください。)
まずは本体と推奨ルールセットをインストールします。
npm i-D secretlint @secretlint/secretlint-rule-preset-recommend
設定ファイル作成のためのコマンドが用意されているので、そちらを使用します。
npx secretlint--init
実行すると.secretlintrc.json
というファイルが作成されます。
ファイルの中身は次のようになっていて、推奨ルールがセットされていることが分かります。
{"rules":[{"id":"@secretlint/secretlint-rule-preset-recommend"}]}
チェック実行用のnpm-scriptsを追加します。
"scripts":{ ...+"secretlint":"secretlint --maskSecrets --secretlintignore .gitignore '**/*'",},
--secretlintignore
は除外ファイルを指定するオプションで、ここでは.gitignore
に書かれたファイルを対象外としています。
--maskSecrets
はエラーメッセージに出力するシークレット情報を***
でマスクしてくれるオプションです。(CIで実行した際のログなどに残らないよう、有効にしておくのがおすすめです)
この状態で
npm run secretlint
を実行すると、対象ファイル内にシークレットデータが無いかチェックしてくれます。
試しに次のようなコードを追加してみてください。
constAWS_KEY='AKIAXXXXXXEXAMPLEKEY';
この状態でnpm run secretlint
を実行すると次のようなエラーが表示されます。
1:24 error[AWSAccessKeyID] found AWS Access Key ID: ******************** @secretlint/secretlint-rule-preset-recommend> @secretlint/secretlint-rule-aws
SecretlintがAWSのアクセスキーを検出し、エラーを出してくれていることが分かりますね。
ここまでコードチェックのためにさまざまな設定を追加してきました。
ここからはHuskyとlint-stagedを使ってGitのコミット前にコードチェックを実行し、問題のあるコードがコミットされないような環境を整えていきます。
ツール名 | 概要 |
---|---|
Husky | Gitのコミットやプッシュ実行時に処理を呼び出すツール (ここではpre-commitフックの際に lint-staged を呼び出します) |
lint-staged | Gitでステージされたファイルに対して処理を呼び出すツール |
https://typicode.github.io/husky/
https://github.com/lint-staged/lint-staged
まずはパッケージをインストールします。
npm i-D husky lint-staged
続いて、Huskyの初期化と設定ファイルの作成を行います。
次のコマンドを実行してください。
npx husky init
husky init
はHusky v9から追加されたコマンドで、以下の処理を実行してくれます。
prepare
コマンドにhusky
を追加(=npm install
時にHuskyの初期化を実行する設定)pre-commit
用の設定ファイル(.husky/pre-commit
)を作成作成された.husky/pre-commit
を次のように更新します。
- npm run test+ npx lint-staged
これでコミット前にlint-staged
が呼び出されるようになります。
https://typicode.github.io/husky/get-started.html
続いてlint-staged
の設定を進めていきます。
プロジェクトルートに.lintstagedrc.js
を作成してください。
まずはNext.jsのドキュメントにしたがって、以下の内容を記述します。
const path=require("path");constbuildEslintCommand=(filenames)=>`next lint --fix --file${filenames.map((f)=> path.relative(process.cwd(), f)).join(" --file ")}`;module.exports={"*.{js,jsx,ts,tsx}":[buildEslintCommand],};
これでコミット時、ステージされたファイルに対してnext lint --fix
が実行されることになります。
ここからさらに手を加えて次のようにします。
const path=require("path");constbuildEslintCommand=(filenames)=>`next lint --fix --file${filenames.map((f)=> path.relative(process.cwd(), f)).join(" --file ")}`;module.exports={+"*":["secretlint --maskSecrets"],+"*.{js,cjs,mjs,json,ts,tsx,css}":["prettier --write"],+"*.{ts,tsx}":["bash -c tsc --noEmit", buildEslintCommand,"markuplint"],};
ここで設定した内容は次の通りです。
対象ファイル | 実行する内容 |
---|---|
全ファイル | Secretlintの秘匿情報チェック |
.js .cjs .mjs .json .ts .tsx .css | Prettierのフォーマット |
.ts .tsx | TypeScriptのコンパイルチェック ESLintの構文チェック Markuplintの構文チェック |
コミット前チェックの設定は以上です。
この状態でファイルをコミットすると、ステージされた各ファイルに対してチェックを実行し、もしエラーがあればコミットを中止してくれます。
チェックを無視してコミットしたいときは、コミット時に-no-verify
か-n
フラグをつけることでスキップができます。
Volta や nvm などの Node.js バージョン管理ツールを使用しているとGUI(VSCodeのGitやSourceTreeなど)からコミットしたときcommand not found
のエラーが出るかもしれません。
その場合、Huskyの実行前にPATHを通す設定が必要になります。
私はVoltaを使用しているため、次のような内容で~/.config/husky/init.sh
を作成しました。
exportVOLTA_HOME="$HOME/.volta"exportPATH="$VOLTA_HOME/bin:$PATH"
詳しくはHuskyのドキュメントや参考記事を参照ください。
https://typicode.github.io/husky/how-to.html#node-version-managers-and-guis
https://zenn.dev/cureapp/articles/f2722061739b51
ここまででかなり開発環境が整ってきましたね。
ここからVSCodeに関する設定をもう少しだけ追加していきます。
Tailwind CSSのクラス名の自動補完をしてくれる、とても便利な拡張機能があるので導入しておきましょう。bradlc.vscode-tailwindcss
をインストールして有効化するだけでOKです。
https://marketplace.visualstudio.com/items?itemName=bradlc.vscode-tailwindcss
https://tailwindcss.com/docs/editor-setup
.vscode/extensions.json
というファイルに、必要なVSCode拡張機能を指定しておきましょう。
{"recommendations":["dbaeumer.vscode-eslint",// ESLint"esbenp.prettier-vscode",// Prettier"yusukehirao.vscode-markuplint",// Markuplint"bradlc.vscode-tailwindcss"// Tailwind CSS IntelliSense]}
こうすることでVSCodeの拡張機能検索欄に@recommended
と入力するだけで、必要な拡張機能が一覧表示されるようになります。(メンバー間で環境を揃える際にとても便利)
ファイル保存時に未importのモジュールを自動で探してimportしてくれる便利な機能があるので有効化しておきましょう。.vscode/settings.json
を次のように更新します。
{"editor.codeActionsOnSave":{"source.fixAll.eslint":"explicit",// ファイル保存時にESLintの自動修正を実行する+"source.addMissingImports":"explicit"// 未importのモジュールを自動で探してimport文を追加する}, ...}
これだけでファイル保存時、VSCodeが未importモジュールを探してimport文を追加してくれるようになります。
最後に、プロジェクトに応じて設定しておくと便利な機能を紹介します。
eslint-plugin-strict-dependencies というプラグインを利用すると、「このコンポーネントはこのファイルからしか読み込めない」というような依存関係のルールを決めることができます。
https://www.npmjs.com/package/eslint-plugin-strict-dependencies
まずはパッケージをインストールします。
npm i-D eslint-plugin-strict-dependencies
例えば「next/link
を直接使わず、ラップしたコンポーネントcomponents/Link.tsx
を必ず使うようにしたい」といった場合、次のような設定となります。
+"plugins":["unused-imports","strict-dependencies"], ..."rules":{ ...+// import先を制限する+"strict-dependencies/strict-dependencies":[+"error",+[+{+"module":"next/link",+"allowReferenceFrom":["components/Link.tsx"],+"allowSameModule":false+},+],+{+"resolveRelativeImport":true+}+]}
こうすることで「components/Link.tsx
以外からはnext/link
をimportできない」という制約が作れます。
設定はプロジェクトに応じてさまざまだと思うのでお好みで色々と設定してみてください。
https://zenn.dev/knowledgework/articles/0994f518015c04#依存関係のチェック(strict-dependencies)
開発環境を整える過程で新しい知識をたくさん得ることができました。
特にESLintに関してはこれまでかなり雰囲気で使っていたところがあったので、整理できてスッキリしています。
ただ、ESLintに関してはv9以降 Flat Config という新たな設定方法へ移行することがアナウンスされていたり、ESLint + Prettier を代替するBiome といったツールも出てきているので、これからもまだまだキャッチアップが必要そうですね。。😱
ここからさらにMarkuplintのプリテンダーの設定をしたり、Secretlintのルールをカスタマイズしたりすることで、さらに便利な環境にしていくことができそうな気がしています。
また、今回はテストツールや CI の設定は行いませんでしたが、今後はこれらも整えてより堅牢な環境を構築できるようになりたいです。
コミット時はシンプルにPrettierやSecretlintのみを、CIでは各種Lintやコンパイラチェックを実行する、というようなフローにしても良いかもしれませんね。
長い記事でしたが最後までお読みいただき、本当にありがとうございました!
本文中で紹介しきれなかった参考記事です。
https://qiita.com/tksst/items/bf62d50b25af69505e8e#9-typescriptの設定変更推奨度3
https://zenn.dev/chida/articles/bdbcd59c90e2e1
https://zenn.dev/t_keshi/scraps/9ddb388bc6975d
https://zenn.dev/rena_h/scraps/fd330154d02f76
https://zenn.dev/chot/articles/bcc178c481a9c2
https://zenn.dev/azukiazusa/articles/start-syntax-checking-with-markuplint
https://zenn.dev/risu729/articles/latest-husky-lint-staged
現状ではNo hard coding ID
というルールのみが追加で有効になるようです。これはIDの重複を防ぐために、要素のid属性をハードコードしている場合に警告を表示するルールです。これに関して制作者のゆうてんさんが解説記事を書いてくれています。↩︎
markuplint には fix コマンドも存在しているのですが、私の環境ではうまく動作させられなかったため今回は使っていません。原因が調査できたら追記したいです。(CLI のドキュメント)↩︎
バッジを受け取った著者にはZennから現金やAmazonギフトカードが還元されます。