JavaやKotlinを長く書いてきて、importの並び順、ソートはフォーマッターにお任せだった。
Next.jsをTypeScriptで書いているプロジェクトでも、Javaと同様、importの順序を統一したいと思い、設定したのでメモ。
環境
Next.js v12.1.5。パッケージマネージャーには Yarn v1.22.15を使用。
ESLintプラグインの導入
importの順序やソート順を変更するプラグインは複数あるが、よく使われている eslint-plugin-import
は、Next.jsの公式ESLint設定である eslint-config-next
に含まれている。
そのため、 create-next-app
でプロジェクトを作成し、 .eslintrc
で next/core-web-vitals
や next
を extends
していれば、プラグインを明示的にインストールしなくても、importの順序の設定が可能。
ただ、ソート順の設定だけでなく、不要なimportの削除もしたいので、eslint-plugin-unused-imports
を追加した。また、Prettierとの共存のため、 eslint-config-prettier
も追加している。
yarn add -D eslint-config-prettier eslint-plugin-unused-imports
ちなみに、 eslint-plugin-import
は、 eslint-config-react-app
や eslint-config-airbnb
などにも含まれている模様。
.eslintrc の記述
以下、JSONCで例を記述。
import順の設定
import/order
の記述方法は以下。
こちらの記事も参考になった。
基本的な並び順は groups
で、パッケージ名などによるカスタマイズは pathGroups
で行う。
react, nextが上に、CSSファイルは最下段に来るようにしている。
また、Amplifyを使用しているため、APIやgraphqlのimportは上に、Figma連携で作成されたUIコンポーネント(ui-components 配下)は下に来るようにし、Figma連携で作られたファイルはESLintの対象外とした。
{ "extends": [ "next/core-web-vitals", // eslint-config-prettier を有効化 "prettier" ], "ignorePatterns": ["src/ui-components/**"], "rules": { // importの並び順設定 "import/order": [ "error", { "groups": [ "builtin", "external", "internal", ["parent", "sibling"], "object", "type", "index" ], "pathGroups": [ { "pattern": "react", "group": "external", "position": "before" }, { "pattern": "next/**", "group": "external", "position": "before" }, { "pattern": "API", "group": "internal", "position": "before" }, { "pattern": "graphql/**", "group": "internal", "position": "before" }, { "pattern": "ui-components/**", "group": "index", "position": "after" }, { "pattern": "**\\.css", "group": "index", "position": "after" } ], "pathGroupsExcludedImportTypes": ["react", "next/**"], "newlines-between": "always", "alphabetize": { "order": "asc", "caseInsensitive": false } } ], // importをファイル先頭に記述 "import/first": "error", // 最後のimportの後に空行を追加 "import/newline-after-import": "error" } }
ちなみに、importだけでなくrequireを用いてもこの設定は有効になる。Amplifyで追加したLambda関数内ではrequireを使っているが、そちらにも効いてくれた。
不要なimportの削除
前述の記事の通り、 plugins
と rules
の追加だけで有効となる。
{ "plugins": ["unused-imports"], "rules": { "unused-imports/no-unused-imports": "error" } }
波かっこ内のソート
これでimportの順序についてはソートできるようになったが、 import { b, a } from ...
を import { a, b } from ...
にするような設定は、 eslint-plugin-import
には存在しない。
調べると、ESLintの標準ルールセットである sort-imports
に存在した。
ignoreMemberSort
が対象だが、オプションの1つであり、これだけを有効化することはできない模様。
もう少し調べてみると、 eslint-plugin-import
に同様の機能追加希望のissueが上がっており、そのコメントに共存させる設定方法が記載されていた。
シンプルに、 ignoreMemberSort
以外はすべてoffにすればいい。
{ "rules": { "sort-imports": [ "error", { "allowSeparatedGroups": true, "ignoreCase": true, "ignoreDeclarationSort": true, "ignoreMemberSort": false, "memberSyntaxSortOrder": ["none", "all", "multiple", "single"] } ], "import/order": [...] } }
VSCodeの設定
エディタとしてVSCodeを使用しているので、ファイル保存時に自動保存をかけたい。
また、これまたJavaのように、不足しているimportがあれば、自動で追加させたい。
以下のように .vscode/settings.json
を記述することで対応できた。
{ "editor.defaultFormatter": "esbenp.prettier-vscode", "editor.formatOnSave": true, // 保存時のアクション "editor.codeActionsOnSave": { // 不足しているimportの追加 "source.addMissingImports": true, // ファイルのfix "source.fixAll": true } }
どんな形式のファイルでもフォーマットしてほしいので、デフォルトのフォーマッターはPrettierにして、保存時にフォーマットするよう設定している。
ESLintの対象となるTypeScriptやJavaScriptファイルは、 editor.formatOnSave
をoffにしておいたほうがいいかとも思ったが、 eslint-config-prettier
を使っているおかげか、今のところ特に問題はなく使えている。
振り返り
importの順序はけっこう癖が出ると思う。
ファイルの修正のついでに人力ソートしてくれる人もいたりするが、それはそれで差分が増えてコードレビューの時に気になったりするので、機械的に統一できるようになってよかった。
eslint-config-next
でルールを決めてくれれば、何もしなくていいので最高なんだけど、そこまではやらないか。本質的な部分ではないし。