Eslint | eslint-plugin-import插件报了import/no-unresolved的错

8,239 阅读3分钟

「这是我参与11月更文挑战的第20天,活动详情查看:2021最后一次更文挑战

在使用eslint的项目中,我们通常希望能够对 ES2015+ (ES6+) import/export的语法进行linting,并防止文件路径和导入名称拼写错误的问题,很幸运当前社区存在这么个插件,它的名字是:eslint-plugin-import。使用它,可以执行以下命令:

npm i eslint-plugin-import

该插件定义了一些规则,如下:

  • 确保导入指向可以解析的文件/模块。(no-unresolved)
  • 确保命名导入对应于远程文件中的命名导出。(named)
  • 在给定默认导入的情况下,确保存在默认导出。(default)
  • 确保导入的命名空间在取消引用时包含取消引用的属性。(namespace)
  • 限制可以在给定文件夹中导入哪些文件 (no-restricted-paths)
  • 禁止使用绝对路径导入模块 (no-absolute-path)
  • 禁止require()使用表达式 (no-dynamic-require)调用
  • 防止导入其他模块的子模块 (no-internal-modules)
  • 禁止导入中的 webpack 加载器语法 (no-webpack-loader-syntax)
  • 禁止模块导入自身 (no-self-import)
  • 禁止模块将具有依赖路径的模块导入回自身 ( no-cycle)
  • 防止 import 和 require 语句中不必要的路径段 ( no-useless-path-segments)
  • 禁止从父目录 (no-relative-parent-imports)导入模块
  • 防止通过相对路径no-relative-packages导入包

在所有规则中,刚开始配置基本会遇到import/no-unresolved的eslint规则报错,原因很简单: eslint无法识别webpack的别名

webpack配置别名

别名,顾名思义就是,创建 import 或 require 的别名,来确保模块引入变得更简单。webpack中的配置一般如下:

// webpack配置文件
module.exports = {
  resolve: {
    alias: {
      assets: path.resolve(__dirname, '../src/assets')
    }
  }
}

此时项目中引用assets文件中的资源就变简单了。

// 原本需要这样,通过相对路径查找
import a from '../../src/assets/1.js'

// 现在只需要这样,路径采用别名,变简单了
import a from 'assets/1.js'

但是当我们使用Eslint时,此时会报错了,因为Eslit解析assets/1.js会报找不到文件,因为这个webpack的别名。因此我们需要进行解决。

解决方案

方案1

在规则中,直接忽略掉以别名为开头的文件,配置如下,虽然这种方式可以解决问题,但并不推荐,因为存在误伤的可能性。

module.exports = {
  // ignore配置webpack配置的别名
  "import/no-unresolved": [2, {"ignore": ["src"]}]
}

方案2

这是推荐采用的方法,将解析到的重新做个映射。

module.exports = {
   settings: {
    'import/resolver': {
      alias: {
        map: [
          // 这里参照webpack的别名配置映射
          ["src", '../src']
        ],
        // 告诉resolver-alias有哪些后缀的文件要解析
        extensions: ['.ts', '.tsx', '.js', '.jsx', '.json'], 
      },
    },
  },
}

优化

以上2种方法解决方式,都要要到webpack的别名声明,那么值每次从webpack进行拷贝配置进行同步总是不合适的,不够高效,因此这里可以做个优化,动态从webpack配置取值。优化如下:

let webpackConfig = require('/路径/webpack.config.js')
if(typeof webpackConfig === 'function'){
   webpackConfig = webpackConfig()
}

/** 解决eslint不能处理webpack别名路径 */
let webpackPathAlias = webpackConfig?.resolve?.alias || {}
// 此时获取的便是别名参数映射了
webpackPathAlias = Object.keys(webpackPathAlias).map(key=>[key,webpackPathAlias[key]]

总结

至此便描述了eslint-plugin-import的规则用处,以及如何解决no-unresolved的问题。