Mear(個人制作物)にESLint, Prettier, Huskyを導入する
ESLint導入
リンターとフォーマッターの学習をしてきたので、自分のプロジェクトにも導入してみる
Next.jsに既存のeslint.jsonがあるけど、eslint.jsに変更(優先順位が高い)
まずはtypescript系ののlintが走るように設定
module.exports = {
root: true,
extends: ["plugin:@typescript-eslint/recommended", "next/core-web-vitals"],
plugins: [],
parser: "@typescript-eslint/parser",
parserOptions: {
project: "./tsconfig.json",
},
rules: {
"@typescript-eslint/no-unused-vars": "error", //宣言されてるけど使用されてない変数をエラーに
"@typescript-eslint/no-explicit-any": "warn", // any型の場合に警告を出す
"@typescript-eslint/no-unsafe-call": "error", // 型安全性が確保されてない関数を呼び出した場合にエラーに
"@typescript-eslint/no-unsafe-member-access": "error", //オブジェクトのメンバーへの型安全性が確保されていないアクセスを検出
"@typescript-eslint/no-unsafe-return": "error", // 型安全性が確保されていない値の返却を検出
},
};
パッケージ追加時にエラー発生
added 5 packages, changed 5 packages, and audited 425 packages in 4s
128 packages are looking for funding
run `npm fund` for details
3 vulnerabilities (1 low, 2 moderate)
To address all issues, run:
npm audit fix --force
Run `npm audit` for details.
脆弱性の報告が出たので、修正
パッケージのアップデート
この記事を参考にする
ncu
Checking /~~~/~~~/~~~~/Frontend/mear/package.json
[====================] 40/40 100%
@google/model-viewer ^3.2.1 → ^3.3.0
@hookform/resolvers ^3.3.1 → ^3.3.2
@radix-ui/react-popover ^1.0.6 → ^1.0.7
@radix-ui/react-select ^1.2.2 → ^2.0.0
@reduxjs/toolkit ^1.9.5 → ^1.9.7
@types/node 20.5.9 → 20.8.6
@types/react 18.2.21 → 18.2.28
@types/react-dom 18.2.7 → 18.2.13
autoprefixer 10.4.15 → 10.4.16
axios ^1.5.0 → ^1.5.1
eslint 8.48.0 → 8.51.0
eslint-config-next 13.4.19 → 13.5.5
lucide-react ^0.277.0 → ^0.287.0
next 13.4.19 → 13.5.5
postcss 8.4.29 → 8.4.31
react-day-picker ^8.8.2 → ^8.9.0
react-hook-form ^7.46.1 → ^7.47.0
react-icons ^4.10.1 → ^4.11.0
react-redux ^8.1.2 → ^8.1.3
zod ^3.22.2 → ^3.22.4
Run ncu -u to upgrade package.json
アップデート
ncu -u
Upgrading /Users/fuku079/Product/Frontend/mear/package.json
[====================] 40/40 100%
@google/model-viewer ^3.2.1 → ^3.3.0
@hookform/resolvers ^3.3.1 → ^3.3.2
@radix-ui/react-popover ^1.0.6 → ^1.0.7
@radix-ui/react-select ^1.2.2 → ^2.0.0
@reduxjs/toolkit ^1.9.5 → ^1.9.7
@types/node 20.5.9 → 20.8.6
@types/react 18.2.21 → 18.2.28
@types/react-dom 18.2.7 → 18.2.13
autoprefixer 10.4.15 → 10.4.16
axios ^1.5.0 → ^1.5.1
eslint 8.48.0 → 8.51.0
eslint-config-next 13.4.19 → 13.5.5
lucide-react ^0.277.0 → ^0.287.0
next 13.4.19 → 13.5.5
postcss 8.4.29 → 8.4.31
react-day-picker ^8.8.2 → ^8.9.0
react-hook-form ^7.46.1 → ^7.47.0
react-icons ^4.10.1 → ^4.11.0
react-redux ^8.1.2 → ^8.1.3
zod ^3.22.2 → ^3.22.4
npm iしたら修正完了
added 1 package, removed 2 packages, changed 31 packages, and audited 424 packages in 26s
126 packages are looking for funding
run `npm fund` for details
found 0 vulnerabilities
lintを走らせてみる
大量のerrorが、、
エラー箇所
npm run lint
> mear@0.1.0 lint
> next lint
./src/app/_components/Common/BottomNavbar/index.tsx
3:1 Error: `react` import should occur before import of `next/link` import/order
6:1 Error: `react-icons/bi` import should occur before import of `react-icons/pi` import/order
./src/app/_components/Common/Navbar/Back/index.tsx
4:1 Error: `react` import should occur before import of `next/link` import/order
./src/app/_components/Form/DatePicker/index.tsx
7:1 Error: `@/components/ui/button` import should occur before import of `@/libs/tailwind/utils` import/order
8:1 Error: `@/components/ui/calendar` import should occur before import of `@/libs/tailwind/utils` import/order
9:1 Error: `@/components/ui/popover` import should occur before import of `@/libs/tailwind/utils` import/order
14:1 Error: `lucide-react` import should occur before import of `@/libs/tailwind/utils` import/order
./src/app/_components/Form/InputButtonCombo/index.tsx
3:1 Error: `react` import should occur before import of `@/components/ui/button` import/order
./src/app/layout.tsx
4:1 Error: `@/libs/font` import should occur before import of `@/store/Provider` import/order
5:1 Error: `./_components/Common/BottomNavbar` import should occur before type import of `next` import/order
./src/app/page.tsx
2:1 Error: `@/app/post/_components/Card` import should occur before import of `@/model/PostCard` import/order
4:1 Error: `next/link` import should occur before import of `@/model/PostCard` import/order
./src/app/post/[postid]/_components/DetailPost/index.tsx
2:17 Error: 'FC' is defined but never used. @typescript-eslint/no-unused-vars
3:1 Error: `react-icons/ai` import should occur after import of `next/image` import/order
4:1 Error: `../../../_components/Card/Header` import should occur after import of `../../../../_components/Common/Navbar/Back` import/order
8:1 Error: `../../../_components/ModelViewer/DynamicModelViewer` import should occur after import of `../../../../_components/Common/Navbar/Back` import/order
10:1 Error: `@/model/PostCard` import should occur after import of `@/components/ui/button` import/order
./src/app/post/_components/Card/index.tsx
9:1 Error: `@/types/Post/types` import should occur before import of `./Header` import/order
./src/app/post/_components/ModelViewer/index.tsx
9:3 Error: ES2015 module syntax is preferred over namespaces. @typescript-eslint/no-namespace
./src/app/post/create/_components/CreatePost/index.tsx
5:1 Error: `react-icons/md` import should occur before import of `../../../../_components/Form/DatePicker` import/order
6:1 Error: `react-icons/ai` import should occur before import of `../../../../_components/Form/DatePicker` import/order
7:1 Error: `@/components/ui/button` import should occur before import of `../../../../_components/Form/DatePicker` import/order
8:1 Error: `@/components/ui/textarea` import should occur before import of `../../../../_components/Form/DatePicker` import/order
9:1 Error: `react-icons/bi` import should occur before import of `../../../../_components/Form/DatePicker` import/order
./src/app/post/create/page.tsx
2:1 Error: `react-redux` import should occur after import of `next/link` import/order
3:1 Error: `@/store/features/shopSlice` import should occur after import of `@/app/post/create/_components/CreatePost` import/order
./src/app/post/page.tsx
2:1 Error: `react` import should occur before import of `@/app/post/[postid]/_components/DetailPost` import/order
./src/app/profile/_components/Header/index.tsx
2:1 Error: `react` import should occur before import of `next/image` import/order
./src/app/profile/_components/Post/index.tsx
1:1 Error: `@/types/Post/types` import should occur after import of `react-icons/md` import/order
2:1 Error: `next/image` import should occur after import of `react` import/order
./src/app/profile/_components/Profile/index.tsx
3:1 Error: `@/types/Profile/types` import should occur before import of `../Header` import/order
5:1 Error: `../Post` import should occur before import of `../TabBar` import/order
6:1 Error: `@/types/Post/types` import should occur before import of `../Header` import/order
./src/app/profile/page.tsx
4:1 Error: `@/model/Profile` import should occur before import of `../_components/Common/Navbar/Back` import/order
5:1 Error: `@/model/PostCard` import should occur before import of `../_components/Common/Navbar/Back` import/order
./src/app/shop/search/_components/Search/index.tsx
3:1 Error: `react` import should occur before import of `next/navigation` import/order
./src/app/shop/search/_components/ShopItem/Container.tsx
3:1 Error: `next/navigation` import should occur before import of `@/store/features/shopSlice` import/order
4:1 Error: `react` import should occur before import of `@/store/features/shopSlice` import/order
7:1 Error: `react-redux` import should occur before import of `@/store/features/shopSlice` import/order
./src/app/shop/search/_components/ShopList/index.tsx
2:1 Error: `react` import should occur before import of `@/store/features/shopSlice` import/order
./src/app/shop/search/page.tsx
2:1 Error: `@/app/_components/Common/Navbar/Back` import should occur before import of `@/app/shop/search/_components/Search` import/order
./src/components/ui/auto-form.tsx
13:1 Error: `react-hook-form` import should occur before import of `zod` import/order
20:1 Error: `@/components/ui/select` import should occur before import of `./form` import/order
27:1 Error: `@hookform/resolvers/zod` import should occur before import of `zod` import/order
28:1 Error: `./button` import should occur before import of `./form` import/order
30:1 Error: `./checkbox` import should occur before import of `./form` import/order
31:1 Error: `./date-picker` import should occur before import of `./form` import/order
32:1 Error: `@/libs/tailwind/utils` import should occur before import of `./form` import/order
35:1 Error: `./accordion` import should occur before import of `./form` import/order
41:1 Error: `./radio-group` import should occur before import of `./switch` import/order
42:1 Error: `./separator` import should occur before import of `./switch` import/order
43:1 Error: `lucide-react` import should occur before import of `zod` import/order
80:55 Error: Unexpected any. Specify a different type. @typescript-eslint/no-explicit-any
96:28 Error: Unexpected any. Specify a different type. @typescript-eslint/no-explicit-any
105:54 Error: Unexpected any. Specify a different type. @typescript-eslint/no-explicit-any
105:59 Error: Unexpected any. Specify a different type. @typescript-eslint/no-explicit-any
117:40 Error: Unexpected any. Specify a different type. @typescript-eslint/no-explicit-any
117:45 Error: Unexpected any. Specify a different type. @typescript-eslint/no-explicit-any
136:16 Error: Unexpected any. Specify a different type. @typescript-eslint/no-explicit-any
136:21 Error: Unexpected any. Specify a different type. @typescript-eslint/no-explicit-any
138:60 Error: Unexpected any. Specify a different type. @typescript-eslint/no-explicit-any
138:65 Error: Unexpected any. Specify a different type. @typescript-eslint/no-explicit-any
141:32 Error: Unexpected any. Specify a different type. @typescript-eslint/no-explicit-any
141:37 Error: Unexpected any. Specify a different type. @typescript-eslint/no-explicit-any
153:7 Error: Unexpected any. Specify a different type. @typescript-eslint/no-explicit-any
205:64 Error: Unexpected any. Specify a different type. @typescript-eslint/no-explicit-any
205:69 Error: Unexpected any. Specify a different type. @typescript-eslint/no-explicit-any
217:45 Error: Unexpected any. Specify a different type. @typescript-eslint/no-explicit-any
221:15 Error: Unexpected any. Specify a different type. @typescript-eslint/no-explicit-any
348:51 Error: Unexpected any. Specify a different type. @typescript-eslint/no-explicit-any
363:31 Error: Unexpected any. Specify a different type. @typescript-eslint/no-explicit-any
416:70 Error: Unexpected any. Specify a different type. @typescript-eslint/no-explicit-any
426:28 Error: Unexpected any. Specify a different type. @typescript-eslint/no-explicit-any
492:56 Error: Unexpected any. Specify a different type. @typescript-eslint/no-explicit-any
492:61 Error: Unexpected any. Specify a different type. @typescript-eslint/no-explicit-any
519:58 Error: Unexpected any. Specify a different type. @typescript-eslint/no-explicit-any
519:63 Error: Unexpected any. Specify a different type. @typescript-eslint/no-explicit-any
537:51 Error: Unexpected any. Specify a different type. @typescript-eslint/no-explicit-any
604:20 Error: Unexpected any. Specify a different type. @typescript-eslint/no-explicit-any
623:55 Error: Unexpected any. Specify a different type. @typescript-eslint/no-explicit-any
623:60 Error: Unexpected any. Specify a different type. @typescript-eslint/no-explicit-any
658:17 Error: Unexpected any. Specify a different type. @typescript-eslint/no-explicit-any
658:22 Error: Unexpected any. Specify a different type. @typescript-eslint/no-explicit-any
659:30 Error: Unexpected any. Specify a different type. @typescript-eslint/no-explicit-any
659:35 Error: Unexpected any. Specify a different type. @typescript-eslint/no-explicit-any
./src/components/ui/calendar.tsx
8:1 Error: `@/components/ui/button` import should occur before import of `@/libs/tailwind/utils` import/order
9:1 Error: `date-fns/locale` import should occur before import of `lucide-react` import/order
57:25 Error: 'props' is defined but never used. @typescript-eslint/no-unused-vars
58:26 Error: 'props' is defined but never used. @typescript-eslint/no-unused-vars
./src/components/ui/date-picker.tsx
7:1 Error: `@/components/ui/button` import should occur before import of `@/libs/tailwind/utils` import/order
8:1 Error: `@/components/ui/calendar` import should occur before import of `@/libs/tailwind/utils` import/order
9:1 Error: `@/components/ui/popover` import should occur before import of `@/libs/tailwind/utils` import/order
14:1 Error: `react` import should occur before import of `date-fns` import/order
./src/components/ui/form.tsx
14:1 Error: `@/components/ui/label` import should occur before import of `@/libs/tailwind/utils` import/order
./src/components/ui/radio-group.tsx
26:17 Error: 'children' is defined but never used. @typescript-eslint/no-unused-vars
./src/store/Provider.tsx
4:1 Error: `react-redux` import should occur before import of `./store` import/order
info - Need to disable some ESLint rules? Learn more here: https://nextjs.org/docs/basic-features/eslint#disabling-rules
(base) fuku079@fukuuranoMacBook-Air mear % npm run npm run lint
npm ERR! Missing script: "npm"
npm ERR!
npm ERR! To see a list of scripts, run:
npm ERR! npm run
npm ERR! A complete log of this run can be found in:
npm ERR! /Users/fuku079/.npm/_logs/2023-10-17T03_56_39_103Z-debug-0.log
(base) fuku079@fukuuranoMacBook-Air mear % npm run lint
> mear@0.1.0 lint
> next lint --dir src/app
./src/app/_components/Common/BottomNavbar/index.tsx
3:1 Error: `react` import should occur before import of `next/link` import/order
6:1 Error: `react-icons/bi` import should occur before import of `react-icons/pi` import/order
./src/app/_components/Common/Navbar/Back/index.tsx
4:1 Error: `react` import should occur before import of `next/link` import/order
./src/app/_components/Form/DatePicker/index.tsx
7:1 Error: `@/components/ui/button` import should occur before import of `@/libs/tailwind/utils` import/order
8:1 Error: `@/components/ui/calendar` import should occur before import of `@/libs/tailwind/utils` import/order
9:1 Error: `@/components/ui/popover` import should occur before import of `@/libs/tailwind/utils` import/order
14:1 Error: `lucide-react` import should occur before import of `@/libs/tailwind/utils` import/order
./src/app/_components/Form/InputButtonCombo/index.tsx
3:1 Error: `react` import should occur before import of `@/components/ui/button` import/order
./src/app/layout.tsx
4:1 Error: `@/libs/font` import should occur before import of `@/store/Provider` import/order
5:1 Error: `./_components/Common/BottomNavbar` import should occur before type import of `next` import/order
./src/app/page.tsx
2:1 Error: `@/app/post/_components/Card` import should occur before import of `@/model/PostCard` import/order
4:1 Error: `next/link` import should occur before import of `@/model/PostCard` import/order
./src/app/post/[postid]/_components/DetailPost/index.tsx
2:17 Error: 'FC' is defined but never used. @typescript-eslint/no-unused-vars
3:1 Error: `react-icons/ai` import should occur after import of `next/image` import/order
4:1 Error: `../../../_components/Card/Header` import should occur after import of `../../../../_components/Common/Navbar/Back` import/order
8:1 Error: `../../../_components/ModelViewer/DynamicModelViewer` import should occur after import of `../../../../_components/Common/Navbar/Back` import/order
10:1 Error: `@/model/PostCard` import should occur after import of `@/components/ui/button` import/order
./src/app/post/_components/Card/index.tsx
9:1 Error: `@/types/Post/types` import should occur before import of `./Header` import/order
./src/app/post/_components/ModelViewer/index.tsx
9:3 Error: ES2015 module syntax is preferred over namespaces. @typescript-eslint/no-namespace
./src/app/post/create/_components/CreatePost/index.tsx
5:1 Error: `react-icons/md` import should occur before import of `../../../../_components/Form/DatePicker` import/order
6:1 Error: `react-icons/ai` import should occur before import of `../../../../_components/Form/DatePicker` import/order
7:1 Error: `@/components/ui/button` import should occur before import of `../../../../_components/Form/DatePicker` import/order
8:1 Error: `@/components/ui/textarea` import should occur before import of `../../../../_components/Form/DatePicker` import/order
9:1 Error: `react-icons/bi` import should occur before import of `../../../../_components/Form/DatePicker` import/order
./src/app/post/create/page.tsx
2:1 Error: `react-redux` import should occur after import of `next/link` import/order
3:1 Error: `@/store/features/shopSlice` import should occur after import of `@/app/post/create/_components/CreatePost` import/order
./src/app/post/page.tsx
2:1 Error: `react` import should occur before import of `@/app/post/[postid]/_components/DetailPost` import/order
./src/app/profile/_components/Header/index.tsx
2:1 Error: `react` import should occur before import of `next/image` import/order
./src/app/profile/_components/Post/index.tsx
1:1 Error: `@/types/Post/types` import should occur after import of `react-icons/md` import/order
2:1 Error: `next/image` import should occur after import of `react` import/order
./src/app/profile/_components/Profile/index.tsx
3:1 Error: `@/types/Profile/types` import should occur before import of `../Header` import/order
5:1 Error: `../Post` import should occur before import of `../TabBar` import/order
6:1 Error: `@/types/Post/types` import should occur before import of `../Header` import/order
./src/app/profile/page.tsx
4:1 Error: `@/model/Profile` import should occur before import of `../_components/Common/Navbar/Back` import/order
5:1 Error: `@/model/PostCard` import should occur before import of `../_components/Common/Navbar/Back` import/order
./src/app/shop/search/_components/Search/index.tsx
3:1 Error: `react` import should occur before import of `next/navigation` import/order
./src/app/shop/search/_components/ShopItem/Container.tsx
3:1 Error: `next/navigation` import should occur before import of `@/store/features/shopSlice` import/order
4:1 Error: `react` import should occur before import of `@/store/features/shopSlice` import/order
7:1 Error: `react-redux` import should occur before import of `@/store/features/shopSlice` import/order
./src/app/shop/search/_components/ShopList/index.tsx
2:1 Error: `react` import should occur before import of `@/store/features/shopSlice` import/order
./src/app/shop/search/page.tsx
2:1 Error: `@/app/_components/Common/Navbar/Back` import should occur before import of `@/app/shop/search/_components/Search` import/order
info - Need to disable some ESLint rules? Learn more here: https://nextjs.org/docs/basic-features/eslint#disabling-rules
:::
src直下のcomponents/uiディレクトリには、shadcnからimportしたコンポーネントが配置されている
このコンポーネントはそのままにしておきたいので、lintが走る箇所を萎める
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint --dir src/app",
"lint:fix": "next lint --fix --dir"
},
fixで修正した後
npm run lint
> mear@0.1.0 lint
> next lint --dir src/app
./src/app/layout.tsx
5:1 Error: `@/libs/font` import should occur before import of `@/store/Provider` import/order
./src/app/post/[postid]/_components/DetailPost/index.tsx
2:17 Error: 'FC' is defined but never used. @typescript-eslint/no-unused-vars
./src/app/post/_components/ModelViewer/index.tsx
9:3 Error: ES2015 module syntax is preferred over namespaces. @typescript-eslint/no-namespace
Modelviewerのファイルとshadcnuiでimportしたコンポーネントは、lintの対象外にしておく
node_modules
.next
out
public
.prettierrc.js
.eslintrc.js
tailwind.config.js
next.config.js
postcss.config.js
src/components/
src/app/post/_components/ModelViewer
Prettier導入
インストール
$ npm i -D prettier eslint-config-prettier
Prettierの設定
{
"printWidth": 120, // 120文字以上で改行
"jsxBracketSameLine": false, // jsxの閉じタグを新しい行に
"tabWidth": 2, // インデントのスペース
"trailingComma": "none", // 配列やオブジェクトの最後の要素にカンマはつけない
"semi": false, // 分の終わりにセミコロンを追加しない
"singleQuote": true // 文字列はシングルクォートで囲む
}
VScodeで保存時にLintやFormatが走るように設定
.vscodeディレクトリを作成し、settings.jsonファイルに追記
{
// ESLintの機能を有効にする
"eslint.enable": true,
// Stylelintの機能を有効にする
"stylelint.enable": true,
// ファイルを保存する際に、自動的にフォーマットを行う
"editor.formatOnSave": true,
// 保存時に実行されるコードアクションを指定
"editor.codeActionsOnSave": {
// 保存時にESLintによる自動修正を行う
"source.fixAll.eslint": true,
// 保存時に不足しているインポートを自動的に追加する
"source.addMissingImports": true
},
// SCSSのバリデーションを無効にする(VSCodeのデフォルトのSCSSバリデーションを避けるため)
"scss.validate": false,
// SCSSファイルに特有の設定
"[scss]": {
// SCSSファイルを保存する際に自動フォーマットを行わない
"editor.formatOnSave": false,
// SCSSファイルを保存する際にStylelintによる自動修正を行う
"editor.codeActionsOnSave": {
"source.fixAll.stylelint": true
}
},
// Stylelintでバリデーションを行うファイルタイプを指定(この場合、SCSSファイルのみ)
"stylelint.validate": ["scss"]
}
husky導入 初
初めてhusky入れてみる
コミット時にリンターやフォーマッターのチェックが走るようになる?ぐらいの解釈です
参考
huskyとlint-stagedをインストール
npm i --dev husky lint-staged
huskyのセットアップ
npx husky install
.huskyというディレクトリができる
.husky
└── _
├── .gitignore
└── husky.sh
`
huskyのprecommitファイルを作成する
npx husky add .husky/pre-commit "npx lint-staged"
中身
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
npx lint-staged
これでpre-commit(git commit実行時)にnpx lint-stagedを実行されるようになる
.lintstagedrc.jsを作成
lintを行うスクリプトが、next.jsだとnext lint --fix
で、実行したいファイルがステージングされたファイル(commitしたいファイル)なので、そうなるようにlint-stagedの設定を行う
const path = require('path')
const buildEslintCommand = (filenames) =>
`next lint --fix --file ${filenames.map((f) => path.relative(process.cwd(), f)).join(' --file ')}`
module.exports = {
'*.{js,jsx,ts,tsx}': [buildEslintCommand]
}
commit時にlintが走るか検証
試しに、import順をルールに逆らってそのままcommitしてみる
成功
ちゃんとlintが通らないとcommitできないようになっている