JavaやKotlinを長く書いてきて、importの並び順、ソートはフォーマッターにお任せだった。
Next.jsをTypeScriptで書いているプロジェクトでも、Javaと同様、importの順序を統一したいと思い、設定したのでメモ。
環境
Next.js v12.1.5。パッケージマネージャーには Yarn v1.22.15を使用。
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
の記述方法は以下。
github.com
こちらの記事も参考になった。
qiita.com
基本的な並び順は 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
に存在した。
eslint.org
ignoreMemberSort
が対象だが、オプションの1つであり、これだけを有効化することはできない模様。
もう少し調べてみると、 eslint-plugin-import
に同様の機能追加希望のissueが上がっており、そのコメントに共存させる設定方法が記載されていた。
github.com
シンプルに、 ignoreMemberSort
以外はすべてoffにすればいい。
{
"rules": {
"sort-imports": [
"error",
{
"allowSeparatedGroups": true,
"ignoreCase": true,
"ignoreDeclarationSort": true,
"ignoreMemberSort": false,
"memberSyntaxSortOrder": ["none", "all", "multiple", "single"]
}
],
"import/order": [...]
}
}
エディタとして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
でルールを決めてくれれば、何もしなくていいので最高なんだけど、そこまではやらないか。本質的な部分ではないし。