ESLint import排序规则未强制React导入置于文件顶部问题排查
React项目ESLint导入顺序规则问题排查与解决
问题描述
基于TypeScript + Vite搭建的React项目,配置ESLint的import/order规则期望强制React导入置于文件最顶部,但出现以下异常:
- 当React导入位于
/vite.svg这类根路径导入下方时,ESLint不触发错误 - 当React导入位于
./assets/react.svg这类相对路径导入下方时,ESLint正常报错:react import should occur before import of ./assets/react.svg eslint(import/order)
项目配置
eslint.config.js
import js from '@eslint/js'; import importPlugin from 'eslint-plugin-import'; import reactHooks from 'eslint-plugin-react-hooks'; import reactRefresh from 'eslint-plugin-react-refresh'; import globals from 'globals'; import tseslint from 'typescript-eslint'; export default tseslint.config( { ignores: ['dist'], }, js.configs.recommended, ...tseslint.configs.recommended, { files: ['**/*.{ts,tsx,js,jsx}'], languageOptions: { ecmaVersion: 2020, sourceType: 'module', globals: { ...globals.browser, React: 'readonly', // Make React available globally }, }, plugins: { 'react-hooks': reactHooks, 'react-refresh': reactRefresh, import: importPlugin, }, rules: { ...reactHooks.configs.recommended.rules, 'react-refresh/only-export-components': ['warn', { allowConstantExport: true }], // formatting semi: ['error', 'always'], indent: ['error', 2], 'no-mixed-spaces-and-tabs': 'error', // import sorting - enhanced rules 'import/first': 'error', // Ensures all imports are at the top of the file 'import/no-duplicates': 'error', // Prevents duplicate imports 'import/newline-after-import': 'error', // Enforces a newline after import statements 'import/order': [ 'error', { groups: ['builtin', 'external', 'internal', 'parent', 'sibling', 'index'], pathGroups: [ { pattern: 'react', group: 'external', position: 'before', }, { "pattern": "assets/**", "group": "internal", "position": "before" }, ], pathGroupsExcludedImportTypes: ['react'], 'newlines-between': 'always', alphabetize: { order: 'asc', caseInsensitive: true, }, }, ], }, } );
App.tsx
import reactLogo from './assets/react.svg'; import { useState } from 'react'; import viteLogo from '/vite.svg'; import './App.css'; function App() { const [count, setCount] = useState(0); return ( <> <div> <a href="https://vite.dev" target="_blank"> <img src={viteLogo} className="logo" alt="Vite logo" /> </a> <a href="https://react.dev" target="_blank"> <img src={reactLogo} className="logo react" alt="React logo" /> </a> </div> <h1>Vite + React</h1> </> ); } export default App;
问题原因
核心问题在于ESLint-plugin-import对导入路径的分组识别:
/vite.svg这类根路径导入被识别为external组(因为它不是以./或../开头的相对路径),和React导入属于同一分组- 当前配置中,
external组内按字母顺序排序,vite.svg首字母v在react的r之后,所以React导入在它下方时符合排序规则,不会触发错误 ./assets/react.svg是相对路径导入,被识别为internal组,而external组默认优先级高于internal组,所以React导入在它下方时会触发错误
解决方案
要让React导入绝对排在所有最前面,有两种可行配置方案:
方案一:强化React在external组的优先级
修改import/order规则,给React的路径匹配添加patternOptions确保覆盖所有React相关导入,并明确让它的优先级高于同组其他导入:
'import/order': [ 'error', { groups: ['builtin', 'external', 'internal', 'parent', 'sibling', 'index'], pathGroups: [ { pattern: 'react', group: 'external', position: 'before', patternOptions: { matchBase: true } // 匹配所有react相关导入,如react-dom }, { pattern: 'assets/**', group: 'internal', position: 'before' }, { pattern: '*/**.svg', // 将所有svg导入归为internal组并后置 group: 'internal', position: 'after' } ], pathGroupsExcludedImportTypes: ['react'], 'newlines-between': 'always', alphabetize: { order: 'asc', caseInsensitive: true, }, warnOnUnassignedImports: true // 开启未分组导入的警告,便于排查 }, ],
方案二:新增专属React分组
直接新增一个优先级最高的react分组,将所有React相关导入归入该组:
'import/order': [ 'error', { groups: ['react', 'builtin', 'external', 'internal', 'parent', 'sibling', 'index'], pathGroups: [ { pattern: 'react', group: 'react', position: 'before' }, { pattern: 'react/**', // 覆盖React子模块,如react-dom、react-router group: 'react', position: 'before' }, { pattern: 'assets/**', group: 'internal', position: 'before' } ], 'newlines-between': 'always', alphabetize: { order: 'asc', caseInsensitive: true, }, }, ],
两种方案都能确保React相关导入排在所有其他导入的最顶部,根据个人偏好选择即可。
内容的提问来源于stack exchange,提问作者tyler
相关产品推荐
相关产品推荐

