はじめに
この記事では、React / TypeScript 環境で ESLint の Flat Config を利用する方法について記載します。
元々 ESLint の設定ファイルは .eslintrc.*
でしたが、v9.0.0(2024年4月リリース)からは Flat Config (eslint.config.js
) がデフォルトになっています。さらに v10.0.0(2024年末から2025年頭にリリース予定)では、.eslintrc.*
が削除される予定です。1
そのため、Flat Config (eslint.config.js
) を利用した設定方法を調べていきます。
開発環境
開発環境は以下の通りです。
- Windows 11
- VSCode
- TypeScript 5.2.2
- React 18.3.1
- Vite 5.3.1
- Node.js 20.15.0
- npm 10.8.1
- ESLint 8.57.0
- @eslint/js 9.6.0
- eslint-plugin-react 7.34.3
- globals 15.8.0
- typescript-eslint 7.15.0
Node.js は以下いずれかのバージョンにする必要があります。
Node.js (^18.18.0, ^20.9.0, or >=21.1.0)2
事前準備
Vite の react-ts
テンプレートで React / TypeScript のプロジェクトを作成しておきます。
npm create vite@latest my-react-ts-app -- --template react-ts
詳細はこちら。
ESLint のインストールと自動設定
以下のコマンドで、ESLint 及び必要なパッケージのインストール、設定ファイル eslint.config.js
の作成ができます。
npm init @eslint/config@latest
コマンド実行後、いくつか質問されるので、以下の選択をします。
React のプラグインは現時点(2024年7月)で ESLint v9 をサポートしていないので、今回は v8 をインストールします。
package.json
には、以下のパッケージが追加されます。
{
...
"devDependencies": {
"@eslint/js": "^9.6.0",
"eslint": "^8.57.0",
"eslint-plugin-react": "^7.34.3",
"globals": "^15.8.0",
"typescript-eslint": "^7.15.0",
...
}
}
-
@eslint/js : ESLint の
recommended
とall
ルール - ESLint : ESLint そのもの
- eslint-plugin-react : React 向けルール
-
globals
- 異なる JavaScript 環境の識別子
- ESLint v8 以前で必要
- typescript-eslint : TypeScript 向けのルール
加えて、設定ファイル eslint.config.js
が作成されます。
import globals from "globals";
import pluginJs from "@eslint/js";
import tseslint from "typescript-eslint";
import pluginReactConfig from "eslint-plugin-react/configs/recommended.js";
export default [
{ files: ["**/*.{js,mjs,cjs,ts,jsx,tsx}"] },
{ languageOptions: { parserOptions: { ecmaFeatures: { jsx: true } } } },
{ languageOptions: { globals: globals.browser } },
pluginJs.configs.recommended,
...tseslint.configs.recommended,
pluginReactConfig,
];
ESLint を実行します。
npx eslint src
ワーニングとエラーが表示されます。
Warning: React version not specified in eslint-plugin-react settings. See https://github.com/jsx-eslint/eslint-plugin-react#configuration .
C:\Users\ymori\Documents\GitHub\flat-config\src\App.tsx
10:5 error 'React' must be in scope when using JSX
react/react-in-jsx-scope
11:7 error 'React' must be in scope when using JSX
react/react-in-jsx-scope
12:9 error Using target="_blank" without rel="noreferrer" (which implies rel="noopener") is a security risk in older browsers: see https://mathiasbynens.github.io/rel-noopener/#recommendations react/jsx-no-target-blank
12:9 error 'React' must be in scope when using JSX
react/react-in-jsx-scope
13:11 error 'React' must be in scope when using JSX
react/react-in-jsx-scope
15:9 error Using target="_blank" without rel="noreferrer" (which implies rel="noopener") is a security risk in older browsers: see https://mathiasbynens.github.io/rel-noopener/#recommendations react/jsx-no-target-blank
15:9 error 'React' must be in scope when using JSX
react/react-in-jsx-scope
16:11 error 'React' must be in scope when using JSX
react/react-in-jsx-scope
19:7 error 'React' must be in scope when using JSX
react/react-in-jsx-scope
20:7 error 'React' must be in scope when using JSX
react/react-in-jsx-scope
21:9 error 'React' must be in scope when using JSX
react/react-in-jsx-scope
24:9 error 'React' must be in scope when using JSX
react/react-in-jsx-scope
25:16 error 'React' must be in scope when using JSX
react/react-in-jsx-scope
28:7 error 'React' must be in scope when using JSX
react/react-in-jsx-scope
✖ 14 problems (14 errors, 0 warnings)
2 errors and 0 warnings potentially fixable with the `--fix` option.
ワーニングの修正
まずはワーニングを修正します。
Warning: React version not specified in eslint-plugin-react settings.
See https://github.com/jsx-eslint/eslint-plugin-react#configuration .
ワーニングメッセージ通り https://github.com/jsx-eslint/eslint-plugin-react を確認すると、version
の値を "detect"
にすることで、自動的に利用中の React バージョンを検知してくれるという記載があります。
// React version. "detect" automatically picks the version you have installed.
// You can also use16.0
,16.3
, etc, if you want to override the detected value.
// It will default to "latest" and warn if missing, and to "detect" in the future
また、version"
は settings
> react
内に記載があります。
そのため、settings
> react
> version: "detect"
という構造で、eslint.config.js
に設定を追加します。
import globals from "globals";
import pluginJs from "@eslint/js";
import tseslint from "typescript-eslint";
import pluginReactConfig from "eslint-plugin-react/configs/recommended.js";
export default [
{
files: ["**/*.{js,mjs,cjs,ts,jsx,tsx}"],
// 追加
settings: {
react: {
version: "detect",
},
},
plugins: {
pluginReactConfig,
},
},
{ languageOptions: { parserOptions: { ecmaFeatures: { jsx: true } } } },
{ languageOptions: { globals: globals.browser } },
pluginJs.configs.recommended,
...tseslint.configs.recommended,
pluginReactConfig,
];
ESLint を実行します。
npx eslint src
ワーニングが解消されていることを確認できます。
C:\Users\ymori\Documents\GitHub\flat-config\src\App.tsx
10:5 error 'React' must be in scope when using JSX
react/react-in-jsx-scope
11:7 error 'React' must be in scope when using JSX
react/react-in-jsx-scope
12:9 error Using target="_blank" without rel="noreferrer" (which implies rel="noopener") is a security risk in older browsers: see https://mathiasbynens.github.io/rel-noopener/#recommendations react/jsx-no-target-blank
12:9 error 'React' must be in scope when using JSX
react/react-in-jsx-scope
13:11 error 'React' must be in scope when using JSX
react/react-in-jsx-scope
15:9 error Using target="_blank" without rel="noreferrer" (which implies rel="noopener") is a security risk in older browsers: see https://mathiasbynens.github.io/rel-noopener/#recommendations react/jsx-no-target-blank
15:9 error 'React' must be in scope when using JSX
react/react-in-jsx-scope
16:11 error 'React' must be in scope when using JSX
react/react-in-jsx-scope
19:7 error 'React' must be in scope when using JSX
react/react-in-jsx-scope
20:7 error 'React' must be in scope when using JSX
react/react-in-jsx-scope
21:9 error 'React' must be in scope when using JSX
react/react-in-jsx-scope
24:9 error 'React' must be in scope when using JSX
react/react-in-jsx-scope
25:16 error 'React' must be in scope when using JSX
react/react-in-jsx-scope
28:7 error 'React' must be in scope when using JSX
react/react-in-jsx-scope
✖ 14 problems (14 errors, 0 warnings)
2 errors and 0 warnings potentially fixable with the `--fix` option.
エラーの修正
エラーは以下の2種類表示されています。
'React' must be in scope when using JSX react/react-in-jsx-scope
Using target="_blank" without rel="noreferrer" (which implies rel="noopener") isa security risk in older browsers:
see https://mathiasbynens.github.io/rel-noopener/#recommendations react/jsx-no-target-blank
react-in-jsx-scope
ひとつ目のエラーについては、React 17 以上では、無効化すべきルールです。今回は React 18 を利用しているので、無効化します。
If you are using the new JSX transform from React 17, you should disable this rule by extending react/jsx-runtime in your eslint config (add "plugin:react/jsx-runtime" to "extends").
ただ、ドキュメントには、"extends"
に "plugin:react/jsx-runtime"
を追加するよう記載がありますが、Flat Config には "extends"
が存在しません。eslint-plugin-react
には、Shareable configs という共有設定ファイルが3つあり、その中に eslint-plugin-react/configs/jsx-runtime
があります。そのため、eslint-plugin-react/configs/jsx-runtime
をインポートして、eslint.config.js
に追加します。
import globals from "globals";
import pluginJs from "@eslint/js";
import tseslint from "typescript-eslint";
import pluginReactConfig from "eslint-plugin-react/configs/recommended.js";
import pluginReactJSXRuntime from "eslint-plugin-react/configs/jsx-runtime.js"; // 追加
export default [
{
files: ["**/*.{js,mjs,cjs,ts,jsx,tsx}"],
settings: {
react: {
version: "detect",
},
},
plugins: {
pluginReactConfig,
},
},
{ languageOptions: { parserOptions: { ecmaFeatures: { jsx: true } } } },
{ languageOptions: { globals: globals.browser } },
pluginJs.configs.recommended,
...tseslint.configs.recommended,
pluginReactConfig,
pluginReactJSXRuntime, // 追加
];
ESLint を実行します。
npx eslint src
'React' must be in scope when using JSX react/react-in-jsx-scope
エラーが解消されていることを確認できます。
C:\Users\ymori\Documents\GitHub\flat-config\src\App.tsx
12:9 error Using target="_blank" without rel="noreferrer" (which implies rel="noopener") is a security risk in older browsers: see https://mathiasbynens.github.io/rel-noopener/#recommendations react/jsx-no-target-blank
15:9 error Using target="_blank" without rel="noreferrer" (which implies rel="noopener") is a security risk in older browsers: see https://mathiasbynens.github.io/rel-noopener/#recommendations react/jsx-no-target-blank
✖ 2 problems (2 errors, 0 warnings)
2 errors and 0 warnings potentially fixable with the `--fix` option.
react/jsx-no-target-blank
もう一つのエラーは、セキュリティ上よろしくない部分なので、コードを修正します。ドキュメントの記載通り target='_blank'
を使っている a
タグに rel='noreferrer'
を追加します。
When creating a JSX element that has an
a
tag, it is often desired to have the link open in a new tab using thetarget='_blank'
attribute. Using this attribute unaccompanied byrel='noreferrer'
, however, is a severe security vulnerability (see noreferrer docs and noopener docs for more details) This rules requires that you accompanytarget='_blank'
attributes withrel='noreferrer'
.
ESLint を実行すると、エラーが全て解消されていることを確認できます。
npx eslint src
所感
-
.eslintrc.*
との差異が思ったより大きい - Flat Config に追いついていない ESLint プラグインもけっこうある(プラグイン自体追いついていない、ドキュメントが追いついていないケースがある)
-
react-in-jsx-scope
デフォルトで無効にしておいて欲しい