1. はじめに
Node.js プロジェクトでの import 文を自動でソートする際に、カスタムエイリアスの設定を変更したとき、そのままでは意図通りの挙動にならなかったのでその対応方法を記す。
2. 前提
Node.js バージョン
$ node -v
#v16.10.0
各種 npm パッケージ(関係ありそうなもののみ列挙)
-
react: ^18.2.0 -
eslint: ^8.15.0 -
eslint-plugin-import: ^2.26.0 -
eslint-plugin-react: ^7.29.4
ディレクトリ構造
src/
├── components
│ ├── atoms
│ │ ├── Foo.tsx
│ │ ├── Bar.tsx
│ ├── molecules
│ │ ├── Hoge.tsx
│ │ ├── Fuga.tsx
├── constant.tsx
..
その他
- VSCode の設定で、ファイル保存時にフォーマットがなされるようにしておく。
- ESLint のセットアップ等については割愛する。
3. 実践
3.1. src/* に対して @/* というエイリアスをあてる
設定
tsconfig.json でエイリアス設定を行う。
{
..
"compilerOptions": {
"baseUrl": "./src",
"paths": {
"@/*": ["./*"],
},
},
..
}
.eslintrc.json で import/order により import 文のソート設定を行う。
{
..
"plugins": ["import", "react"],
"parserOptions": {
"sourceType": "module",
"project": "./tsconfig.json"
},
"ignorePatterns": [".eslintrc.json", "tsconfig.json"],
"rules": {
"sort-imports": 0,
"import/order": [
2,
{
"alphabetize": { "order": "asc" },
"newlines-between": "always",
}
]
}
}
フォーマット
適当なファイルを保存した時のソート例を示す。
import React from 'react';
import { Foo } from '@/components/atoms/Bar';
import { Bar } from '@/components/atoms/Foo';
import { Fuga } from '@/components/molecules/Fuga';
import { Hoge } from '@/components/molecules/Hoge';
import { piyo } from'@/constant';
eslint-plugin-import では groups というものがあり、import する対象によって分類され、まずそれ単位でソートされる。1
import React from 'react' は external という group に該当し、その他は internal の group に属する。先に react が import されているのは、この group の優先度がデフォルトでは、 external > internal となっているためである。
また、各 group の中では、今回はアルファベット順(昇順)にソートされるように .eslintrc.json で設定したため、そのような並び替えになっている。
この例では、問題のなさそうなソートが実現できているが、次のような場合を考える。
3.2. src/components/* に対して @@/* というエイリアスをあてる
src/components/* が肥大化してきたため、src/* の他の部分と区別したエイリアスを設定したくなったとする。
設定
{
..
"compilerOptions": {
"baseUrl": "./src",
"paths": {
"@/*": ["./*"],
+ "@@/*": ["./components/*"],
},
},
..
}
フォーマット
先ほどと同じファイルを保存してみる。
この時、エイリアスを追加したので、@/components → @@/ の変更を行なって保存をする。
import { Foo } from '@@/atoms/Bar';
import { Bar } from '@@/atoms/Foo';
import { Fuga } from '@@/molecules/Fuga';
import { Hoge } from '@@/molecules/Hoge';
import React from 'react';
import { piyo } from'@/constant';
今回は、react の import 文よりも先に components/* の import 文が来てしまっている。好みの問題だが、できれば先に react などの external なものは先にソートされてほしい。
そこで、.eslintrc.json に以下の変更を加える。
{
..
"plugins": ["import", "react"],
"parserOptions": {
"sourceType": "module",
"project": "./tsconfig.json"
},
"ignorePatterns": [".eslintrc.json", "tsconfig.json"],
"rules": {
"sort-imports": 0,
"import/order": [
2,
{
"alphabetize": { "order": "asc" },
"newlines-between": "always",
+ "pathGroupsExcludedImportTypes": ["builtin", "object"],
+ "pathGroups": [
+ {
+ "pattern": "@@/**",
+ "group": "external",
+ "position": "after"
+ }
+ ]
}
]
}
}
pathGroups で、特定のパスに対してソートする位置を指定することができる。今回は、@@/** というパスの import 文を external groups の 後(after) に来るように設定している。
ところが、 @@/ は external group に属し、この group に対してはデフォルトでは pathGroups の設定が有効にならないようになっている(pathGroupsExcludedImportTypes に external が含まれている)。2そこで、pathGroupsExcludedImportTypes からこれを外すような設定も必要となる。
以上により、次のようなソート結果となる。
import React from 'react';
import { Foo } from '@@/atoms/Bar';
import { Bar } from '@@/atoms/Foo';
import { Fuga } from '@@/molecules/Fuga';
import { Hoge } from '@@/molecules/Hoge';
import { piyo } from'@/constant';
これで違和感のない自然なソート順序となった。
4.
参考にさせていただいたページ
-
https://github.com/import-js/eslint-plugin-import/blob/main/docs/rules/order.md#groups-array ↩
-
@/だと external にならずに、@や@@/だと external group になるようだが、裏は取れていない ↩