Next.js +TypeScriptで環境構築!ESLint + Prettierの導入から解析自動化までやってみた
はじめに
こんばんは、バックエンドエンジニア見習い1年目のkuraoです!
「Next.js+TypeScript」でアプリケーション環境を構築する機会があり、その際リンターツール導入の手順などと併せてドキュメントとしてまとめていたので、アウトプットを兼ねてこの場に書き連ねて行こうと思います!
実現したい事
今回のアプリケーション環境構築で目指す所としては以下です。
-
Next.js
環境のアプリを構築 - Next.js環境のアプリに
TypeScript
を導入 -
ESLint + Prettier
を導入して、コードの一貫性を高め、かつバグ回避を行う -
husky + lint-staged
を導入して、ESlintとPrettierによるコード解析を自動化する
前提
-
node
がインストールしてある事(ver. 14.15.4) -
yarnパッケージ
がインストールしてある事(ver. 1.22.4) - GitHubにこのアプリケーションを管理するための新規リポジトリを作成しておいてください
- アプリケーション環境は以下のようになります
"dependencies": {
"next": "10.0.9",
"react": "17.0.2",
"react-dom": "17.0.2"
},
"devDependencies": {
"@types/node": "14.14.36",
"@types/react": "17.0.3",
"@typescript-eslint/eslint-plugin": "^4.19.0",
"@typescript-eslint/parser": "^4.19.0",
"eslint": "^7.22.0",
"eslint-config-prettier": "8.1.0",
"eslint-plugin-react": "^7.23.1",
"husky": "^5.2.0",
"lint-staged": "^10.5.4",
"prettier": "2.2.1",
"typescript": "^4.2.3"
},
今回導入するツールについて超ざっくりと説明
ESLint
静的解析ツール。設定したルールに従ってバグを発見してくれます。
Prettier
コード整形ツール。設定したオプションに従ってコードを良い感じに整形してくれます。
husky
git commit
やgit push
をフックして、scriptsを実行してくれるツールです。
lint-staged
staging
されているコードに対して、lintを実行してくれるツールです。
本記事の大まかな流れ
-
Next.js
アプリの雛形を構築 - GitHubの新規リポジトリのmainへ上記アプリを登録
- Next.js環境に
TypeScript
を導入 -
ESLint
+Prettier
を導入 -
husky
+lint-staged
導入 - 動作確認
1. Next.jsアプリケーションの雛形を作成
まずはじめに、Next.jsアプリケーションの雛形を作成したいのでcreate-next-appを実行します。
npx create-next-app new-app
cd new-app
package.jsonの中身がnpx create-next-app
を実行した時点でどうなっているか、試しに見てみます。
nameプロパティやscriptsプロパティは良いとして、despendencies
を見てみると、next
, react
, react-dom
というパッケージがインストールされていることが確認できます。
これがNext.jsアプリケーションを動かす上で必要なパッケージという事になります。
{
"name": "new-app",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start"
},
"dependencies": {
+ "next": "10.0.9",
+ "react": "17.0.2",
+ "react-dom": "17.0.2"
}
}
2. リモートブランチにnew-appを登録
次に、上記で作成したnew-app
を、作成済みのリモートのブランチに登録します。
# new-appでgitを初期化
git init
git add .
git commit -m "first commit"
# リモートのベースブランチがmasterになっている場合
git branch -M main
# このnew-appをリモートリポジトリのnew-appへ登録
git remote add origin git@github.com:username/new-app.git
# new-appをmainブランチへpush
git push -u origin main
3. Next.js環境にTypeScriptを導入
導入の方法はVervelに示されている導入方法に概ね従っている感じです。
tsconfig.jsonを作成
new-app
のトップディレクトリ配下にtsconfig.json
を作成します。
このtsconfig.jsonをトップディレクトリ配下に作成する事で、new-appがTypeScriptプロジェクトであることを宣言した事になります。
The presence of a tsconfig.json file in a directory indicates that the directory is the root of a TypeScript project. The tsconfig.json file specifies the root files and the compiler options required to compile the project. (from TypeScript公式)
touch tsconfig.json
# tsconfig.jsonを開き、設定を記述
code ./tsconfig.json
tsconfig.json
には以下のような設定を記述しました。
各プロパティについて(ざっくり)
各プロパティに関する説明についてはtsconfig.jsonの全オプションを理解する(随時追加中)という記事がわかりやすいので、TypeScript公式と合わせて確認すれば良い感じなのではと思います。
compilerOptions
compilerOptions内に各プロパティと、それに対する値を指定していきます。
target
プロジェクトで使用しているJSバージョンに古いブラウザに対応していない場合があります。その際にはJSのコードを古いブラウザために変換してあげなければなりません。そこでtarget
にES5
と記述する事でES5のコードへ変換してくれるようになります。
lib
target
に指定しているJSバージョンではサポートされていないライブラリの中で、使用したいライブラリをここに設定します。
baseUrl
ファイルを探しに行く際の開始地点を指定します。./
とした場合、トップレベルディレクトリを指定した事になり、以下のような階層構造になります。
baseUrl
┣━━ sample.ts
┣━━ src
┃ ┣━━ index.ts
┃ ┗━━ test.ts
┗━━━ tsconfig.json
こうした場合、例えばtest.ts
にてindex.ts
のコンポーネントをimportしたいとなった際には 以下のようにして絶対パス
で参照ができるようになります。
import { Home } from "src/index"
console.log(Home)
typeRoots
コンパイルしたいパッケージを指定します。逆に、ここに指定したパッケージ以外のものはコンパイルされません。
以下ではnode_modules/@types
というのを指定しています。これはこの後インストールするTypeScriptパッケージである@types系のパッケージを指します。
allowJS
TypeScriptファイルへの、JavaScriptファイルのimportを許可します。例えば以下のように、.js
を.ts
ファイルへimportが可能になります。
export const Sample = () => {
console.log("hello")
}
import { Sample } from "src/sample.js"
Sample()
// -> hello
skipLibCheck
宣言ファイルの型チェックをスキップします。コンパイル時間の節約と引き換えに、型システムの正確性を捨てるという設定になります。
strict
プログラムの正しさをより強く保証するために、幅広い型チェックの動作を可能にする設定です。
これをtrue
に設定すると、上記リンクに飛んだ先のStrict
以下にリストアップされているオプション全てを有効にします。
forceConsistentCasingInFileNames
TypeScriptは実行しているファイルシステムの大文字・小文字の区別ルールに従います。このオプションをtrue
に設定すると、例えばSample.ts
というファイルがあったとしてこれをimportしたいとなった際、sample.ts
として大文字部分を小文字にしてimportするとエラーを出力するようになります。
noEmet
JavaScriptのソースコード、ソースマップ、宣言などのコンパイラ出力ファイルを実行しないようにすることができます。
これにより、Babelなどの別ツールがTypeScriptファイルをJavaScript環境で実行可能なファイルに変換する処理を行う余地ができます。
esModuleInterop
ES6モジュールの仕様では、名前空間のインポート(import * as x
)はオブジェクトでなければならないとされています。
このesModuleInterop
をtrueに設定することで、TypeScriptがこれをrequire("x")
と同じように扱うことによりTypeScriptはimportを関数として扱い、呼び出しを可能にします。
module
プログラムのモジュールシステムを設定します。今回esnextの構文を使用します。
moduleResolution
モジュール解決方法を設定します。node
もしくはclassic
のどちらかを指定します。classicを使うことは最近ではないとのことなのでnode
を指定で問題ないかと思います。
resolveJsonModule
拡張子が.json
のモジュールのimportを可能にします。これには、import用の静的なJSON形式の型
を生成も含まれます。
TypeScriptではデフォルトでJSONファイルの解決をサポートしていないのでtrue
に設定します。
isolatedModules
isolatedModules
を設定すると、シングルファイルのトランスパイル処理で正しく解釈できない特定のコードを書いた場合に、TypeScriptがwarningを出力してくれるようになります。
以下で、isolatedModulesを設定した場合にエラーを出力するようになるコードの例を示します。
- TypeScriptでは型のimportが可能です。(ここではsomeTypeを指します)
- しかし、
isolatedModules
を設定している場合、exportしようとするとエラーを出力します。someTypeに値が設定されていないためです。
import { someType, someFunction } from "someModule";
someFunction();
// someTypeには値が指定されていないのでエラーになる
export { someType, someFunction };
jsx
JavaScriptファイルでJSXコンストラクトがどのように出力されるかを制御します。
これは、.tsx
ファイルで始まるJSファイルの出力にだけ影響します。
preserve
を設定すると、JSXを変更せずに.jsx
ファイルを出力します。
include
プログラムに含めるファイル名またはパターンの配列を指定します。
これらのファイル名は、tsconfig.jsonファイルを含むディレクトリからの相対パスで解決を行います。
例えば、以下のァイルをinclude
に設定したとすると
{
"include": ["src/**/*", "test/**/*"]
}
以下のチェックの付いたファイルだけを含めることになります。
.
├── scripts ⨯
│ ├── lint.ts ⨯
│ ├── update_deps.ts ⨯
│ └── utils.ts ⨯
├── src ✓
│ ├── client ✓
│ │ ├── index.ts ✓
│ │ └── utils.ts ✓
│ ├── server ✓
│ │ └── index.ts ✓
├── tests ✓
│ ├── app.test.ts ✓
│ ├── utils.ts ✓
│ └── tests.d.ts ✓
├── package.json
├── tsconfig.json
└── yarn.lock
(from https://www.typescriptlang.org/tsconfig#include)
exclude
exclude
では、上記で挙げたinclude
とは逆に、含めないファイルを指定します。
{
"compilerOptions": {
"target": "es5",
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"baseUrl": "./",
"typeRoots":
"node_modules/@types"
],
"allowJs": true,
"skipLibCheck": true,
"strict": false,
"forceConsistentCasingInFileNames": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve"
},
"include": [
"next-env.d.ts",
"**/*.ts",
"**/*.tsx"
],
"exclude": [
"node_modules"
]
}
このタイミングで一旦、yarn dev
を実行してローカルサーバーを立ち上げてみましょう。
yarn dev
しかし、以下のようなエラーが表示されて立ち上がらないと思います。
TypeScriptの実行に必要なパッケージ(typescript, @type/react, @type/node )
がインストールされていないためにTypeScriptでサーバーを起動できないよ的なことが書いてあります。
It looks like you're trying to use TypeScript but do not have the required package(s) installed.
Please install typescript, @types/react, and @types/node by running:
yarn add --dev typescript @types/react @types/node
If you are not trying to use TypeScript, please remove the tsconfig.json file from your package root (and any TypeScript files in your pages directory).
ので、エラーメッセージに書いてある通りにパッケージをインストールしてあげます。
パッケージはyarn add
に--dev
オプションを付与してインストールします。
yarn add --dev typescript @types/react @types/node
インストールしたパッケージがpackage.jsonのdevDependenciesに追加されていることを確認してみます。
tsconfig.json
のtypeRoots
で指定したnode_modules/@types
はこれらパッケージを参照することになります。
{
"name": "new_talktape_client_web",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev -p 4000",
"build": "next build",
"start": "next start",
},
"dependencies": {
"next": "10.0.9",
"react": "17.0.2",
"react-dom": "17.0.2"
},
"devDependencies": {
+ "@types/node": "14.14.36",
+ "@types/react": "17.0.3",
+ "typescript": "^4.2.3"
}
}
- 少々逸れますが、dependenciesとdevDependenciesの違いについてざっくり説明しておきます。
-
dependencies
-
本番環境
でも利用するパッケージやその依存関係をここに追加します。依存関係
とは、パッケージを動作させるために必要なパッケージです。手動でパッケージ類をインストールする場合は依存関係のあるパッケージも追加しないと動きませんが、npm
やyarn
を利用してインストールする事により、依存関係
パッケージもインストールしてくれるため、私たちは依存関係については気にする必要がありません。
-
-
devDependencies
-
開発環境
やテスト環境
で利用するパッケージやその依存関係をここに追加します。タイミング的には本番用にビルドする時
で、ビルドしたタイミングでここへ追加したパッケージ類は排除されます。今回導入するESLint
やhusky
やlint-staged
はこちらに追加する事になります。
-
-
インストールが完了しましたら、今度は上手くいくはずですのでもう一度ローカルサーバーを立ててみましょう。
yarn dev
以上でNext.js環境へのTypeScriptの導入は完了ですので、リンターツール導入へ参ります。
4. ESLint + Prettier を導入
ESLint + Prettier 導入で参考にさせて頂いた記事
インストールするパッケージ
-
ESLint
- eslint
- typescript-eslint
- @typescript-eslint/parser
- @typescript-eslint/eslint-plugin
-
上記4つのパッケージ導入詳細
-
Prettier
4-1. ESLint導入
ESLintに必要なパッケージのインストール
まずはESLintから導入していきます。yarn add
に--dev
オプションを付与して必要となるパッケージをインストールしていきましょう。
yarn add --dev eslint typescript @typescript-eslint/parser @typescript-eslint/eslint-plugin eslint-plugin-react
# ESLintのバージョンを確認
./node_modules/.bin/eslint --version
v7.22.0
TypeScriptにESLintを設定するためのファイルを作成
次に、TypeScriptにESLintを設定するための設定ファイルであるtsconfig.eslint.json
を作成します。
これは先ほど作成したtsconfig.json
ファイルとは異なり、ESLintを設定するために
作成します。
touch tsconfig.eslint.json
# 設定を記述するのでエディタを開きます
code ./tsconfig.eslint.json
ファイルを開いたら、設定事項を記述していきます。
-
extends
:./tsconfig.jsonの設定事項を継承 -
includes
:指定したファイルにESLintを含める -
excludes
:指定したファイルをESLintに含めない
{
"extends": "./tsconfig.json",
"includes": [
"src/**/*.ts",
"src/**/*.tsx",
".eslintrc.json",
],
"exclude": [
"node_modules",
"dist"
]
}
ESLint用の設定ファイルを作成
次にESLint設定そのもの
を記述していくファイル.eslintrc.json
をトップレベルディレクトリ配下に作成し、必要な設定事項を記述していきます。
touch .eslintrc.json
# .eslintrc.jsonファイルを開く
code ./.eslintrc.json
各プロパティについて(ざっくり)
各プロパティについての詳細はコチラ:ESLint - Configure ESLint
root
.eslintrc.json
がプロジェクトのルートに配置されているかをチェックします。指定がない場合は上位階層へ設定ファイルを探しにいきます。
env
環境を指定できます。
-
browser
:trueを指定すると、ブラウザのグローバル変数を有効にします。 -
node
:trueを指定すると、Node.jsのグローバル変数やスコープを有効にします -
es6
:trueを指定すると、ECMAScript6のモジュールを除いた全ての機能が使用可能になります。
settings
今回ここでreact
のバージョンを指定しています。detect
とする事で、インストールしている既存のReactのバージョンを参照してくれます
参考:https://github.com/yannickcr/eslint-plugin-react
parserOptions
ESLintでは、サポートするJavaScriptの言語オプションを指定できます。
デフォルトではESLintはECMAScript5の構文のみをサポートします。
parserOptions
では、この設定を上書きして、ECMAScript6とJSXのサポートを有効にすることができます。
指定できるオプションは以下です。
-
ecmaVersion
:デフォルトではECMAScript5、使用したいECMAScriptを指定してください。 -
sourceType
:"script"もしくは"module"を指定できます。 -
ecmaFeatures
:使用したい構文を追加で指定できます。- jsx:trueを指定することでJSXの使用を有効化します
plugins
ESLintはサードパーティ製のプラグインの使用をサポートしています。
インストールしたサードパーティ製のプラグインをESLintで有効にするには、plugins
プロパティに配列で指定します。
extends
ESLintによるオススメのルールを適用することができます。
rulesで1個ずつ指定するのが大変な部分はここに推奨設定を指定しちゃうのが良いかと思います。
rules
rules
では指定したプロパティに対してo ~ 2
の数値を指定して設定を行います。
-
0
:指定したruleをOFFに設定します -
1
:指定したruleをONに設定します。rule違反を犯した場合はwarning
を返します -
2
:指定したruleをONに設定します。rule違反を犯した場合はerror
を返します
{
"root": true,
"env": {
"browser": true,
"es6": true,
"node": true
},
"settings": {
"react": {
"version": "detect"
}
},
"parser": "@typescript-eslint/parser",
"parserOptions": {
"sourceType": "module",
"ecmaVersion": 2020,
"ecmaFeatures": {
"jsx": true
},
"project": "./tsconfig.eslint.json"
},
"plugins": ["react", "@typescript-eslint"],
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/eslint-recommended",
"plugin:@typescript-eslint/recommended",
"plugin:react/recommended",
"prettier"
],
"rules": {
"@typescript-eslint/explicit-function-return-type": 0,
"@typescript-eslint/no-explicit-any": 0,
"@typescript-eslint/no-empty-function": 0,
"react/prop-types": 0,
"react/react-in-jsx-scope": 0,
"no-empty-function": 0,
"@typescript-eslint/ban-ts-comment": 0
}
}
ESLintの設定ファイルの記述は以上です、次はESLintを実行するためのスクリプトを書いていきます。
ESLint実行用のscriptsを記述
次にpackage.jsonファイルに、ESLint実行用のscriptsを記述していきます。
{
...
"scripts": {
...
// 型チェック用
"check-types": "tsc --noEmit",
// .ts, .tsx ファイルのリンターを実行
"lint": "eslint \"src/**/*.{ts,tsx}\"",
// .ts, .tsx のリンターで引っかかったものの中で修正出来るならば修正を行う
"lint:fix": "eslint \"src/**/*.{ts,tsx}\" --fix",
// 上記3つのscriptsを一斉実行
"test-all": "npx yarn-run-all lint check-types lint:fix"
},
...
}
以上でscriptsの記述が済みましたので、早速scriptsを実行してみましょう。
試しにcheck-types
を実行してみます。するとScirptsが走って、正常に通ったかと思います(型エラーになるような記述が今はないはずなので)
yarn check-types
# 自動で実行される部分
yarn run v1.22.4
$ tsc --noEmit
✨ Done in 1.86s.
実行できず、もし以下のようなエラーが出てしまった場合は、エラーメッセージにて示している通りのコマンドを実行してあげることで解決できます。
npm WARN lifecycle The node binary used for scripts is
/var/folders/wz/y5x9_lts6hn_wcsj3_902q8w0000gn/T/yarn--1616765067702-
0.6028041030632163/node but npm is using /usr/local/bin/node itself.
Use the `--scripts-prepend-node-path` option to include the path for the node binary npm was executed with.
# 以下のコマンドを実行したら、再度 $ yarn check-types を実行してみてください
yarn config set scripts-prepend-node-path true
上記ではcheck-types
を実行してみましたが、他のscriptsも実行してみて正常に動作するかどうか確認してみてください。
以上でESLintの設定は一通り完了しました。次はコードを整形するPrettier
の設定を行っていきます。
4-2. Prettier導入
必要なパッケージのインストール
yarn add
に--dev
、--exact
を付与して実行します。--exactオプションを付与するとバージョンを固定してインストールします。
yarn add --dev --exact prettier eslint-config-prettier
.eslintrc.jsonファイルにPrettierの設定を加える
Prettierの設定で何故ESLintの設定ファイルを開く必要があるのかと思うかもしれませんが、ESLintによるコード整形とPrettierによるコード整形が競合して上手くいかないことがあったり、チーム開発している場合だと自分のブランチとチームメンバーのブランチとでコード整形に差異が生まれる可能性があるので、ここでPrettierとESLintの競合を無くす
設定を行っていいきます。
code ./eslintrc.json
prettier
をextends
プロパティの最後の行
に記述してください。最後の行に記述することで、ESLintによるコード整形を上書きして、Prettierだけでコード整形してくれるようになります。
.eslintrc.json
ファイルが、下に記述したオプションで上にある記述を上書きすることがこれを可能にしてくれています。
{
"root": true,
// ...
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/eslint-recommended",
"plugin:@typescript-eslint/recommended",
"plugin:react/recommended",
+ "prettier"
],
// ...
}
Prettierの設定ファイルを作成
次にPrettierの設定ファイルである.prettierrc
ファイルを作成して、Prettierそのものの設定を記述します。
{
"singleQuote": true,
"semi": false,
"trailingComma": "all"
}
VSCode側でのPrettierの設定
VSCodeを使用している場合にはこの設定を行うと、良い感じにコード整形を行ってくれるようになります。
まずはトップレベルディレクトリ配下に.vscode
ディレクトリが存在しない場合は作成し、.vscode配下にsettings.json
ファイルを生成します。
mkdir .vscode
touch .vscode/settings.json
ファイルを生成したら、設定を記述をします。
各プロパティの詳細については公式を参照すると良いかなと思います:https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode
{
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
},
"eslint.format.enable": false,
"editor.formatOnSave": true,
"[javascript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[json]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[typescript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"editor.lineNumbers": "on",
"editor.rulers": [80],
"editor.wordWrap": "on",
"eslint.packageManager": "yarn",
"files.insertFinalNewline": true,
"files.trimTrailingWhitespace": true,
"npm.packageManager": "yarn",
"typescript.enablePromptUseWorkspaceTsdk": true
}
Prettier実行用のscriptsを記述
次に、package.jsonにPrettierでコードを整形するためのscriptsを記述していきます。
{
// ...
"scripts": {
// ...
"check-types": "tsc --noEmit",
"lint": "eslint \"src/**/*.{ts,tsx}\"",
"lint:fix": "eslint \"src/**/*.{ts,tsx}\" --fix",
// Prettierによるコード整形
+ "format": "prettier --write .",
// "format"を追加
+ "test-all": "npx yarn-run-all lint check-types format lint:fix"
},
// ...
}
Prettierの設定は以上です。次は、huskt
とlint-staged
を導入して、commit, push
する直前にリンター、コード整形、型チェック
などを行うよう設定を行っていきます。
5. husky + lint-staged導入
次はhusky
とlint-staged
なる物を導入していきます。
参考
-
husky
:https://typicode.github.io/husky/#/-
husky
についてはバージョンの差によって仕様が変わっていたりするので、公式を中心に参照するのがよきかなと思います。
-
-
lint-staged
:https://github.com/okonet/lint-staged- コチラに関してはあくまで参考程度に参照させて頂いておりました。例えばインストールコマンドの
npx mrm lint-staged
は本記事では用いておりません。と言いますのも、コチラを使用した場合simple-git-hooks
というGitフックが自動で設定されるのですが、Gitフックの役割はhuskyにお任せすることにしたためです。
- コチラに関してはあくまで参考程度に参照させて頂いておりました。例えばインストールコマンドの
-
husky
+lint-staged
そもそもhuskyとlint-stagedって何?
冒頭でも軽く説明しましたが、この2つがどんな役割を担ってくれるのかという所を改めて説明しますと
-
husky
:pre-commit
やpre-push
などのフックにpackage.jsonに既に記述してあるscriptsを設定することで、gitのコミット
やプッシュ
する直前に登録したscriptsを実行してくれるツールです。 -
lint-staged
:stageに上がっているファイルに対してlintをかけてくれるツールです。
といった具合に、この2つを併せて使うことにより、stageに上がっているアプリケーションのコードに対してコミットやプッシュをする前にリンターの実行を差し込むことが出来るようになります。
ワークフローのざっくりとしたイメージとしては、例えば「git commitする前にlintでチェックを入れたい」とするならば、
-
git add
してgit commit
する -
git commit
した瞬間husky
が走る -
lint-staged
が走る - stageに上がっているファイルに対して
lint
実行用のscriptsが走る
みたいな感じになります。
前置きが長くなりまして申し訳ありません!ここからは導入へと参ります。
husky, lint-stagedパッケージのインストール
husky
とlint-staged
もまたdevDependenciesに追加したいので、yarn add
に--dev
オプションを付与してパッケージをインストールします
yarn add --dev husky lint-staged
一応package.json
に上記パッケージがインストールされていることを確認します。
{
// ...
"devDependencies": {
"@types/node": "14.14.36",
"@types/react": "17.0.3",
"@typescript-eslint/eslint-plugin": "^4.19.0",
"@typescript-eslint/parser": "^4.19.0",
"eslint": "^7.22.0",
"eslint-config-prettier": "8.1.0",
"eslint-plugin-react": "^7.23.1",
+ "husky": "^5.2.0",
+ "lint-staged": "^10.5.4",
"prettier": "2.2.1",
"typescript": "^4.2.3"
},
// ...
}
lint-stagedの設定
先にlint-staged
の設定から行っていきますので、package.json
ファイルを開いて、lint-staged
というプロパティを新たに追加します。
ここでは「lint-staged
が実行されたら.ts
, .tsx
ファイルに対して、lint
, format
, lint:fix
のscriptsを実行してくれい」というようなことを指定しています。
{
// ...
"dependencies": {
// ...
}
"devDependencies": {
//...
},
+ "lint-staged": {
+ "*.{ts,tsx}": [
+ "yarn lint",
+ "yarn format",
+ "yarn lint:fix"
+ ]
+ }
}
huskyの設定
次にhusky
の設定も行なっていきましょう。
huskyの設定ファイル.huskyを生成
先ほどhusky
というパッケージをインストールしましたが、それとは別に以下のようにyarn husky install
というコマンドを実行します。
このコマンドを実行することで、husky.shファイル
を含む.huskyフォルダ
をトップレベルディレクトリ配下に作成します。
yarn husky install
次にpackage.json
のscriptsのprespare
にhusky install
を設定します。
prepare
は、yarn install
で全てのインストールが終了した後に実行されるscriptsです。
{
// ...
"scripts": {
"dev": "next dev -p 4000",
"build": "next build",
"start": "next start",
+ "prepare": "husky install",
// ...
},
// ...
}
上記コマンドを実行することで、トップレベルディレクトリ配下に.husky
が作成されていることを確認します。
new-app
┣━━ .husky
┃ ┣━━ _
┃ ┗━━ .gitignore
┃
pre-commitで実行するscriptsを設定
次にgit commit
直前に実行させるためのscriptsを設定していきます。
上記で作成した.husky
ディレクトリ配下にpre-commit
というファイルを作成して、その中に設定を記述します。
touch .husky/pre-commit
code .husky/pre-commit
commit前にはlint-staged
を実行するよう設定します、つまりlint
, format
, lint:fix
を実行するようにします。
#!/bin/sh
# $0はこのファイルを指します
."$(dirmname "$0")/_/husky.sh"
# yarn lint-stagedを実行
yarn lint-staged
pre-commitの設定は以上です、次にpre-pushの設定です。
pre-pushで実行するscriptsを設定
git push
直前の実行させるためのscriptsを設定していきます。
pre-commit同様、.husky
ディレクトリ配下にpre-push
ファイルを作成し、その中に設定を記述します。
touch .husky/pre-push
code .husky/pre-push
pushの直前にcheck-types
、つまり型チェック
を実行するよう設定します。
# $0はこのファイルを指します
."$(dirname "$0")/_/husky.sh"
# yarn check-typesを実行
yarn check-types
pre-pushの設定は以上になります。
pre-commit, pre-pushファイルの実行権限を変更
次に、上記で設定したpre-commit
, pre-push
ファイルに対して実行権限
を付与します。
これをしない場合、pre-commitとpre-pushファイルが実行できない可能性があるので注意です。
chmod a+x .husky/pre-commit
chmod a+x .husky/pre-push
以上でhusky
とlint-staged
の設定は完了です!
では、試しにcommitとpushをしてみて、正常に動作するかを確認してみましょう。
husky + lint-stagedの動作確認
上記で設定したhusky
とlint-staged
が正常に動作するかをチェックしていきます。
動作確認用のファイルを作成
まずは、src
ディレクトリ配下に動作確認用のファイルとして、test.ts
とtest.tsx
ファイルを用意して、ファイル内に整形されていない汚いコードを記述してください。
加えて、src/index.tsx
ファイル内に、誤った形で関数の呼び出しを行なってください。これを行う意図としては型チェックを行うためです。
export const hello = (name: string) => {
console.log(name)
}
export const hello2 = (name: string) => {
console.log(name)
}
export const hello3 = (name: string) => {
console.log(name)
}
export const hello4 = (name: string) => {
console.log(name)
}
export const hello = (name: string) => {
console.log(name)
}
export const hello2 = (name: string) => {
console.log(name)
}
export const hello3 = (name: string) => {
console.log(name)
}
export const hello4 = (name: string) => {
console.log(name)
}
import { NextPage } from 'next'
import Head from 'next/head'
import styles from '../styles/Home.module.css'
// 追加
import { hello } from './test-for-tsx'
const Home: NextPage = () => {
// 追加
// hello()の引数にはstring型を指定していますが
// あえてnumber型を入れて型エラーになることをチェックします
+ hello(12)
return (
<div className={styles.container}>
// ...
</div>
)
}
export default Home
commitとpushを実行
次に、実際にgit commit
とgit push
を行なってみましょう。
commit
まずはpre-commit
にはyarn lint-staged
が走るように設定したのでした、つまりlint
, format
, lint:fix
が走るように設定しました。
正常にこれらsctiptsを実行してくれるか確認してみましょう。
# stagingに上げる
git add .
git commit -m "check pre-commit"
# .husky/pre-commitに設定したscriptsが走る/
yarn run v1.22.4
$ /Users/username/new-app/node_modules/.bin/lint-staged
✔ Preparing...
✔ Running tasks...
✔ Applying modifications...
✔ Cleaning up...
✨ Done in 4.18s.
[main .....] check pre-commit
scirptsが実行された結果、Done
と表示されていれば正常に動作したということになりますので、上記で作成したtest.ts
, test.tsx
ファイル(インデントとかバラバラの汚いコード書いたやつ)は、以下のようにコード整形などがされているはずですので、確認してみてください。
export const hello = (name: string) => {
console.log(name)
}
export const hello2 = (name: string) => {
console.log(name)
}
export const hello3 = (name: string) => {
console.log(name)
}
export const hello4 = (name: string) => {
console.log(name)
}
push
次にpre-push
では、yarn check-types
が走るよう設定したのでした、つまり型チェック
を行うよう設定しました。
正常に型チェック
を行なってくれるか確認してみましょう。
git push
# .husky/pre-pushに設定したscriptsが走る
yarn run v1.22.4
$ tsc --noEmit
src/pages/index.tsx:7:9 - error TS2345: Argument of type 'number' is not assignable to parameter of type 'string'.
7 hello(12)
~~
Found 1 error.
正常に型チェックを行なってくれました!
ちなみに型チェックに成功する場合は、以下のようにDone
と表示され、GitHubのリモートブランチへpushされることになります。
git push
# .husky/pre-pushに設定したscriptsが走る
yarn run v1.22.4
$ tsc --noEmit
✨ Done in 1.45s.
おわりに
以上で Next.js + TypeScript + ESLint + Prettier + husky + lint-staged での環境構築は完了です。
フロントエンドの環境構築全般に言えることなんですが、各プロパティが何をやってくれているのかみたいな理解については、曖昧な部分がほとんどなのでもうちょっと頑張ります。。。😇
何かご指摘やご意見などありましたら、ご気軽に頂けると大変助かります!
最後まで読んで頂きありがとうございました🙇♂️
Discussion