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