likes
comments
collection
share

monorepo模式下,eslint报路径不对的问题

作者站长头像
站长
· 阅读数 29

场景

现有一个pnpm管理的monorepo仓库如下

  1. packages下存在两个以上的vite vue项目,并且在各个包分别管理自己的vite.config.tstsconfig.json,分别配置了项目的目录别名如 {@: './src'}
  2. 项目eslintrc.js位于根目录,统一管理整个项目的代码格式,并且引入了eslint-config-import插件
  3. 项目中使用了别名例如在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.jsonvite.config.ts也对应改一下。如此规则路径解析就从默认的eslint-import-resolver-node/index.js变为eslint-import-resolver-alias/index.js,匹配到相应的map规则时,就用我们的自定义路径去解析。

转载自:https://juejin.cn/post/7367328756955906057
评论
请登录