💡

Vite, React, TS, ESLint, Prettier, Husky, lint-staged... etc Setup

2023/02/07に公開

はじめに

コミットやコードのルール・規約はちゃんと守れていますか?

できるだけヒューマンエラーを無くすためにも、技術に頼ってルールを守れるように仕組み化しましょう。

コミットルールはconventional commit

https://www.conventionalcommits.org/ja/v1.0.0/

コーディングルールはJacaScript Standard Style,ts-standard

https://github.com/standard/standard/blob/master/docs/README-ja.md
https://github.com/standard/ts-standard

に従います。

今回使用する技術は以下の通りです。

技術 バージョン URL
Vite 4.1.1 https://ja.vitejs.dev/
React 18.0.27 https://ja.reactjs.org/
TypeScript 4.9.5 https://www.typescriptlang.org/
ESLint 8.33.0 https://eslint.org/
Prettier 2.8.3 https://prettier.io/
Husky 8.0.3 https://typicode.github.io/husky/#/
Lint-staged 13.1.0 https://github.com/okonet/lint-staged
Commitlint 17.4.2 https://commitlint.js.org/#/
Commitizen 4.3.0 http://commitizen.github.io/cz-cli/
pnpm 7.26.3 https://pnpm.io/ja/

大まかな流れは以下の通りです。

  1. Viteでプロジェクトの雛形を作成
  2. Commitlint, Commitizen, Huskyを導入してコミットメッセージを自動化
  3. ESlint, Prettier, Lint-stagedを導入して静的解析とフォーマットを自動化

Viteでプロジェクトの雛形を作成

pnpmを使用します。以下を実行すると質問してくれるので回答しましょう。

pnpm create vite

回答は以下の通りです。

✔ Project name: … vite-project
✔ Select a framework: › React
✔ Select a variant: › TypeScript + SWC

完了すると、以下のコマンドが出てくるので開発サーバーが立ち上がるか確認します。

cd vite-project
pnpm install
pnpm run dev

ちなみに、追加されたパッケージは以下の通りです。

dependencies:
+ react 18.2.0
+ react-dom 18.2.0

devDependencies:
+ @types/react 18.0.27
+ @types/react-dom 18.0.10
+ @vitejs/plugin-react-swc 3.1.0
+ typescript 4.9.5
+ vite 4.1.1

開発サーバーが立ち上がったことを確認できたら、コミットしときましょう。

git init
git add .
git commit -m "first commit"

Commitlint, Commitizen, Huskyを導入してコミットメッセージを自動化

Huskyを追加するため、以下を実行

pnpm add -D husky

Git Hooksを有効にするため、以下を実行

pnpm husky install

続いて、Commitlintを追加するため、以下を実行

pnpm add -D @commitlint/cli @commitlint/config-conventional

設定を追加するため、package.jsonに以下を追加

package.json
"commitlint": {
    "extends": [
      "@commitlint/config-conventional"
    ]
  },

commit-msgというHookを追加するため、以下を実行

pnpm husky add .husky/commit-msg  'npx --no -- commitlint --edit ${1}'

続いて、Commitizenを追加するため、以下を実行

pnpm add  -D commitizen

commitizenを初期化するため、以下を実行

pnpm commitizen init cz-conventional-changelog --pnpm --save-dev --save-exact

git commit時にcommitizenを起動させたいため、以下を実行

pnpm husky add .husky/prepare-commit-msg  'exec < /dev/tty && node_modules/.bin/cz --hook || true'

これで、いつも通り以下を実行すると、commitizenが起動するので、あとは適宜入力してください。

git add .
git commit

一応git logなどでコミットが行われているかご確認ください。

ESlint, Prettier, Lint-stagedを導入して静的解析とフォーマットを自動化

ESLintを追加するため、以下を実行

pnpm add -D eslint

ESLintの初期化をするため、以下を実行

pnpm eslint --init

回答は以下の通り

✔ How would you like to use ESLint? · style
✔ What type of modules does your project use? · esm
✔ Which framework does your project use? · react
✔ Does your project use TypeScript? · No / Yes
✔ Where does your code run? · browser
✔ How would you like to define a style for your project? · guide
✔ Which style guide do you want to follow? · standard-with-typescript
✔ What format do you want your config file to be in? · JavaScript
Checking peerDependencies of eslint-config-standard-with-typescript@latest
The config that you've selected requires the following dependencies:

eslint-plugin-react@latest eslint-config-standard-with-typescript@latest @typescript-eslint/eslint-plugin@^5.0.0 eslint@^8.0.1 eslint-plugin-import@^2.25.2 eslint-plugin-n@^15.0.0 eslint-plugin-promise@^6.0.0 typescript@*
✔ Would you like to install them now? · No / Yes
✔ Which package manager do you want to use? · pnpm

すると、@typescript-eslint/parser@">=5.0.0 <6.0.0"を追加してくれと言われたので、以下を実行

pnpm add -D @typescript-eslint/parser@">=5.0.0 <6.0.0"

作成された.eslintrc.cjsは以下の通り

.eslint.cjs
module.exports = {
  env: {
    browser: true,
    es2021: true
  },
  extends: [
    'plugin:react/recommended',
    'standard-with-typescript'
  ],
  overrides: [
  ],
  parserOptions: {
    ecmaVersion: 'latest',
    sourceType: 'module'
  },
  plugins: [
    'react'
  ],
  rules: {
  }
}

確認のため、以下を実行

pnpm eslint . 

すると以下のようなエラーが出る。

Error while loading rule '@typescript-eslint/dot-notation': You have used a rule which requires parserServices to be generated. You must therefore provide a value for the "parserOptions.project" property for @typescript-eslint/parser.

エラー文に従って、.eslint.cjsを変更

.eslint.cjs
module.exports = {
  env: {
    browser: true,
    es2021: true
  },
  extends: [
    'plugin:react/recommended',
    'standard-with-typescript'
  ],
  overrides: [
  ],
  parserOptions: {
    ecmaVersion: 'latest',
    sourceType: 'module',
+   project: './tsconfig.json'
  },
  plugins: [
    'react'
  ],
  rules: {
  }
}

再度、eslintを実行

pnpm eslint .
Warning: React version not specified in eslint-plugin-react settings. See https://github.com/jsx-eslint/eslint-plugin-react#configuration .

...
✖ 20 problems (20 errors, 0 warnings)
  5 errors and 0 warnings potentially fixable with the `--fix` option.

React Versionを指定しろとのことだったので、Versionを記述する。

また、react/react-in-jsx-scopeのエラーはReact17以降は必要ないので、extendsにplugin:react/jsx-runtimeを追加。(以下参照)

https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/react-in-jsx-scope.md

その結果が以下の通り

.eslint.cjs
module.exports = {
  env: {
    browser: true,
    es2021: true
  },
  extends: [
    'plugin:react/recommended',
    'standard-with-typescript',
+   'plugin:react/jsx-runtime',
  ],
  overrides: [
  ],
  parserOptions: {
    ecmaVersion: 'latest',
    sourceType: 'module',
    project: './tsconfig.json'
  },
  plugins: [
    'react'
  ],
  rules: {
  },
+  settings: {
+    react: {
+      version: '18.2.0'
+    }
+  }
}

他のエラーは--fixオプションをつけると大体解決します。

あとは、tsconfig.jsonを以下のように変更したり

tsconfig.json
{
  "compilerOptions": {
    "target": "ESNext",
    "useDefineForClassFields": true,
    "lib": ["DOM", "DOM.Iterable", "ESNext"],
    "allowJs": false,
    "skipLibCheck": true,
    "esModuleInterop": false,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "module": "ESNext",
    "moduleResolution": "Node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "react-jsx"
  },
-  "include": ["src"],
+  "include": ["vite.config.ts", "src"],
  "references": [{ "path": "./tsconfig.node.json" }]
}

App.tsxに型を追加したりするくらいです。また、eslintのエラー表示が気になる人は.eslintignoreなどを適宜設定してください。

続いて、prettierとeslintのprettier用の設定を追加するため、以下を実行

pnpm add -D prettier eslint-config-prettier

以下のような.prettierrcを設定してください。設定はお好みでどうぞ。
また、ESLintとPrettierはvscodeで拡張機能があるので、追加し設定しておきましょう。

.prettierc
{
  "printWidth": 80,
  "tabWidth": 2,
  "useTabs": false,
  "semi": false,
  "singleQuote": true,
  "trailingComma": "none",
  "bracketSpacing": true,
  "jsxBracketSameLine": false,
  "arrowParens": "avoid"
}

ESLintの設定ファイルにprettierを追加

.eslintrc.cjs
module.exports = {
  env: {
    browser: true,
    es2021: true
  },
  extends: [
    'plugin:react/recommended',
    'standard-with-typescript',
    'plugin:react/jsx-runtime',
+   'prettier'
  ],
  overrides: [],
  parser: '@typescript-eslint/parser',
  parserOptions: {
    ecmaVersion: 'latest',
    sourceType: 'module',
     project: './tsconfig.json'
  },
  plugins: ['react'],
  rules: {
  },
  settings: {
    react: {
      version: '18.2.0'
    }
  }
}

続いて、lint-stagedを追加するため、以下を実行

pnpm add -D lint-staged

package.jsonに以下を追加

packaje.json
 "lint-staged": {
    "*.{js,jsx,ts,tsx}": [
      "eslint --fix",
      "prettier --write"
    ]
  }

pre-commitのhooksを作成するため、以下を実行

pnpm husky add .husky/pre-commit "pnpm lint-staged"

これで、コミットする前にステージングされているファイルで条件に合うファイルがあったらESLintとPrettierが動いて直してくれる。エラーが出ればコミットされないので安全な開発ができます。

ついでに、buildも追加しておきましょう。

pre-commit
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"

pnpm lint-staged
+ pnpm build

最後に、以下を実行

git add .
git commit

実行結果は以下の通りです。

まず、pre-commitにあるlint-stagedが行われ、完了すればbuildが行われます。
無事、buildが完了すればcommitizenが起動するので、適宜入力します。最後にcommitlintがチェックして問題なければコミットされます。

✔ Preparing lint-staged...
✔ Running tasks for staged files...
✔ Applying modifications from tasks...
✔ Cleaning up temporary files...

> vite-project@0.0.0 build /Users/{???}/vite-project
> tsc && vite build

vite v4.1.1 building for production...
✓ 33 modules transformed.
dist/index.html                   0.46 kB
dist/assets/react-35ef61ed.svg    4.13 kB
dist/assets/index-d526a0c5.css    1.42 kB │ gzip:  0.74 kB
dist/assets/index-0f3be939.js   143.62 kB │ gzip: 46.17 kB
cz-cli@4.3.0, cz-conventional-changelog@3.3.0

? Select the type of change that you're committing: chore:    Other changes that don't modify src or test files
? What is the scope of this change (e.g. component or file name): (press enter to skip) 
? Write a short, imperative tense description of the change (max 93 chars):
 (69) add ESLint, Prettier, lint-staged to automate static analysis of code
? Provide a longer description of the change: (press enter to skip)
 
? Are there any breaking changes? No
? Does this change affect any open issues? No
[master 1cca30d] chore: add ESLint, Prettier, lint-staged to automate static analysis of code
 7 files changed, 1672 insertions(+), 11 deletions(-)
 create mode 100644 .eslintrc.cjs
 create mode 100755 .husky/pre-commit
 create mode 100644 .prettierrc

作成したプロジェクトのリポジトリを貼っておきます。
https://github.com/kapureka6174/vite-project-template

以上です。

お疲れ様でした。

Discussion