monorepo模式下,eslint报路径不对的问题
场景
现有一个pnpm管理的monorepo仓库如下
- packages下存在两个以上的vite vue项目,并且在各个包分别管理自己的
vite.config.ts
和tsconfig.json
,分别配置了项目的目录别名如{@: './src'}
- 项目
eslintrc.js
位于根目录,统一管理整个项目的代码格式,并且引入了eslint-config-import
插件 - 项目中使用了别名例如在
router.ts
中const Layouts = () => import('@/layouts/index.vue')
在这种场景下,eslint
会报import/no-unresolved
问题
原因分析
通过源码我们可以看到,在默认没有任何配置的情况下,no-unresolved
规则会使用eslint-import-resolver-node\index.js
去进行模块解析路径,最终调用resolve-sync
这包, 执行模块路径解析
if ((/^(?:\.\.?(?:\/|$)|\/|([A-Za-z]:)?[/\\])/).test(x)) {
var res = path.resolve(absoluteStart, x);
if (x === '.' || x === '..' || x.slice(-1) === '/') res += '/';
var m = loadAsFileSync(res) || loadAsDirectorySync(res);
if (m) return maybeRealpathSync(realpathSync, m, opts);
} else if (includeCoreModules && isCore(x)) {
return x;
} else {
var n = loadNodeModulesSync(x, absoluteStart);
if (n) return maybeRealpathSync(realpathSync, n, opts);
}
因为我们的路径不符合相对路径,也不是node核心模块(fs、path等),所以会进入最后一个else
function loadNodeModulesSync(x, start) {
var thunk = function () { return getPackageCandidates(x, start, opts); };
var dirs = packageIterator ? packageIterator(x, start, thunk, opts) : thunk();
if (x.includes('main-vue3/layouts/index.vue')) {
console.log(dirs, x)
}
for (var i = 0; i < dirs.length; i++) {
var dir = dirs[i];
if (isDirectory(path.dirname(dir))) {
var m = loadAsFileSync(dir);
if (m) return m;
var n = loadAsDirectorySync(dir);
if (n) return n;
}
}
}
我们在这里加入我们的调试代码,可以看到输出如下
[
'E:\\my\\micro-app\\packages\\app-main-vue3\\src\\router\\node_modules\\main-vue3\\layouts\\index.vue',
'E:\\my\\micro-app\\packages\\app-main-vue3\\src\\node_modules\\main-vue3\\layouts\\index.vue',
'E:\\my\\micro-app\\packages\\app-main-vue3\\node_modules\\main-vue3\\layouts\\index.vue',
'E:\\my\\micro-app\\packages\\node_modules\\main-vue3\\layouts\\index.vue',
'E:\\my\\micro-app\\node_modules\\main-vue3\\layouts\\index.vue',
'E:\\my\\node_modules\\main-vue3\\layouts\\index.vue',
'E:\\node_modules\\main-vue3\\layouts\\index.vue',
'C:\\Users\\cpx\\.node_modules\\main-vue3\\layouts\\index.vue',
'C:\\Users\\cpx\\.node_libraries\\main-vue3\\layouts\\index.vue'
] main-vue3/layouts/index.vue
我们的路径被当作依赖包,去找node_modules
去了,所以最终eslint是无法通过我们在子包里配置好的别名去识别我们的以来路径
解决方案
安装eslint-import-resolver-alias
包,并在eslintrc.js
加入以下规则
settings: {
'import/resolver': {
alias: {
map: [
['main-vue3', './packages/app-main-vue3/src'],
['child-vue3', './packages/app-child-vue3/src'],
],
extensions: ['.ts', '.js', '.json', '.vue'],
},
},
}
对应的tsconfig.json
和vite.config.ts
也对应改一下。如此规则路径解析就从默认的eslint-import-resolver-node/index.js
变为eslint-import-resolver-alias/index.js
,匹配到相应的map
规则时,就用我们的自定义路径去解析。
转载自:https://juejin.cn/post/7367328756955906057