当我们在开发Vue项目的过程中,有时需要创建某些文件,
如 less文件(定义公共样式、清空默认样式等),
而当我们需要将这些文件以@别名的形式导入到如main.js文件中,可能会产生错误信息
(当然,这里的错误是指你已经正确安装"less"及"less-loader"等相关依赖的情况下仍有错误提示)
0 前置环境
通过vue-cli的方式创建了vue2项目,且在安装时自定义由脚手架自动安装ESLint语法检查,
项目结构如下:
假设我们需要一个公共样式,且以less文件的形式定义,且正确安装了less相关依赖包,
具体内容如下(在src目录下创建了styles文件夹存放公共样式文件,如common.less)
创建完毕后,需要使用到该样式,那么通常会在main.js中进行导入,
具体如下图:
注:这里的@别名,并没有进行配置,这是Vue-CLI 的默认 @ 别名配置,自带的,无需配置就可使用
但是!既然是自带的默认配置且可以正常使用,那为什么还会报错呢??????
1 报错原因
当你尝试在main.js文件中,以上图形式 import ‘@/styles/common.less’ 导入less文件,
报错原因如下:
ESLint 报错(import/extensions 规则):
默认禁止在导入路径中使用文件扩展名(如 .less)
但 Webpack 需要明确扩展名才能解析非 JS 文件
也就是说,这种导入形式与ESlint的语法规则冲突,ESLint不允许在导包时添加文件扩展名
OK,那既然不允许添加文件扩展名,那咱就不添加!
当我们改成 import ‘@/styles/common’ 进行导入时,报错又来了,如下图:
有别于之前的报错,这次报错的原因是为何呢?
Webpack 解析失败:
当省略扩展名时(import '@/styles/common'),Webpack 不知道要找 .less 文件
需要配置 Webpack 自动解析 .less 扩展名
也就是说,当我们省略了文件扩展名,又会引起Webpack 解析的报错,
由于省略了扩展名,它找不到对应的文件
2 解决方案
2.1 方案一
我们可以通过相对路径导入的方式,即可解决
2.2 方案二
2.2.1 实现步骤
# 1. 步骤 1:修改 ESLint 规则(允许 .less 扩展名)
# 1.1 安装eslint-import-resolver-alias,以便ESLint能够解析别名
终端执行命令:npm install eslint-import-resolver-alias --save-dev
# 1.2 在项目根目录的 .eslintrc.js 中添加规则:
module.exports = {
root: true,
env: {
node: true
},
extends: [
'plugin:vue/essential',
'@vue/standard'
],
parserOptions: {
parser: '@babel/eslint-parser'
},
settings: {
'import/resolver': {
alias: {
map: [['@', './src']],
extensions: ['.js', '.vue', '.less'] // 告诉 ESLint 如何解析别名
}
}
},
rules: {
'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
'import/extensions': [
'error',
'always',
{
js: 'never', // .js 文件永远不要写扩展名
vue: 'never', // .vue 文件永远不要写扩展名
less: 'always' // .less 文件必须写扩展名
}
]
}
}
# 步骤 2 在vue.config.js文件中添加如下配置
const { defineConfig } = require('@vue/cli-service')
const path = require('path') // 添加 path 模块引入
module.exports = defineConfig({
transpileDependencies: true,
configureWebpack: {
resolve: {
alias: {
'@': path.resolve(__dirname, 'src') // 确保 @ 别名指向 src 目录
},
// 保留默认扩展名,并添加 .less
extensions: ['.js', '.vue', '.json', '.less']
}
}
})
对方案二作用的解释
当安装了 eslint-import-resolver-alias 以及 配置了 以上两个文件
意味着,
当要导入.js或.vue文件时,对应的文件扩展名必须省略;
当要导入.less文件时,对应的文件扩展名必须添加
.eslintrc配置文件中settings和rules配置项的作用:
settings配置项:
告诉 ESLint 如何解析别名
rules配置项:
规定导包时哪些文件必须写文件扩展名,哪些文件必须省略文件扩展名
值为never,则必须省略;值为always,则必须添加
默认值为always,所以,即使less不显式写上也是可以的
但是,推荐做法是显式写上去,方便团队其他成员知晓导包方式
vue.config.js配置文件中extensions配置项的作用:
当我们要导一个省略文件扩展名的包时,
它会告知webpack查找该文件的优先级,先按.js文件进行查找,以此类推......
同时,针对于第三方包,内部导入的文件,如less文件,省略了文件扩展名,
那么webpack在查找时,也会按该配置依次查找到对应文件
2.2.2 实现效果
3 知其所以然
3.1 疑问一
从 2 的方案中,我们得知方案一的导入方式可以采用相对路径的写法
但是我们注意到,该 导入方式 是加了文件扩展名的,
在还没有配置方案二的情况下,按照ESLint的规则,讲道理应该会报错的,但是没有!
原因如下:
1 相对路径豁免规则
ESLint的import/extensions规则默认禁止在导入路径中使用扩展名(如.less),
但对相对路径(如./styles/common.less)通常存在豁免机制。
这是因为相对路径直接指向具体文件,扩展名被视为路径的必要组成部分,而非冗余信息。
2 别名路径的严格检查
当使用@/styles/common.less时,ESLint将其视为模块导入而非文件路径。
根据ESLint默认规则,模块导入不应包含扩展名(仅.js/.json可省略),
因此触发import/extensions错误
3.2 疑问二
关于@别名的配置,我在jsconfig.json中有相关的默认配置,为何还需要在vue.config.js文件中配置
原因如下:
1 jsconfig.json 的作用:
为 IDE(如 VS Code) 和 TypeScript 提供路径解析支持
让编辑器能识别 @/ 路径,提供智能提示和跳转功能
不影响 Webpack 的构建过程
2 vue.config.js 的作用:
为 Webpack 提供构建时的路径解析规则
当代码中出现 import '@/styles/common.less' 时,Webpack 需要知道 @ 指向哪个目录
直接影响项目的编译和运行
3.3 疑问三
之前没有在vue.config.js中配置上@别名,
但是在main.js中以这种形式 import ‘@/utils/vant-ui-comp’ 导入js文件,
为什么可以正常运行
原因如下:
3.4 总结
方案一可以运行成功,
原因在于ESLint对其存在豁免机制
方案二可以运行成功,
原因在于:
解决了ESLint要求文件扩展名省略的问题,方案直接规定哪些文件的扩展名可以省略,哪些不可以;
也间接解决了如果省略扩展名从而导致webpack找不到对应文件的问题