Less 本身不识别 @ 别名,必须加 ~ 前缀才能触发 Webpack 模块解析,否则按文件系统相对路径查找导致 404;@import、url() 和 data-uri() 均需加 ~(如 @import "~@/styles/vars.less"),~ 是 Webpack 显式划分解析边界的信号,漏掉则路径交由文件系统处理而失效。

Less 本身不识别 @ 别名,必须加 ~ 前缀才能触发 Webpack 的模块解析机制,否则一律按文件系统相对路径查找,必然 404。
@import 中写 @/xxx.less 报错
Less 编译器只认真实文件路径,@ 是 Webpack resolve.alias 提供的 JS 层能力,.less 文件不会走那一套。报错信息如 Less resolver error: '@/styles/vars.less' wasn't found 就是典型表现。
- 错误写法:
@import "@/styles/vars.less";—— Less 直接去当前 .less 所在目录下找@/styles/...子目录 - 正确写法:
@import "~@/styles/vars.less";——~是 Webpack 给 loader 的信号,表示“这是模块路径,请按 alias 解析” - 如果配置了
lessOptions.paths(比如paths: [path.resolve(__dirname, 'src/styles')]),可简写为@import "~vars.less";
url() 和 data-uri() 里用 @/ 路径失败
和 @import 同理,url('./xxx.png') 在 Less 里默认被 css-loader 当作绝对路径处理,不自动解析 . 和 ..;而 url('@/assets/logo.png') 更是直接当字面量字符串,Webpack 根本不介入。
- 推荐方案:
background: url('~@/assets/logo.png');——~触发模块解析,最稳 - 备选方案:加
resolve-url-loader(放在less-loader之前),它能重写url()中的相对路径 - 临时 hack:
background: url('\./assets/logo.png');—— 反斜杠转义点号,仅适用于单层相对路径,不推荐长期用 -
data-uri()同样要加~,例如data-uri('~@/icons/close.svg')
Webpack 配置漏掉 ~ 或 paths 导致 AntD 等第三方库引入失败
像 @import '~antd/es/style/themes/index.less'; 报错,不是 antd 没装好,而是 less-loader 没配 paths 或 Webpack resolve.alias 没覆盖到 ~antd。
立即学习“前端免费学习笔记(深入)”;
- 最稳做法:在
less-loader的lessOptions中显式加paths,例如paths: [path.resolve(__dirname, 'node_modules')] - 或在 Webpack
resolve.alias中补全:'~antd': path.resolve(__dirname, 'node_modules/antd'),并确保该 alias 同时被less-loader和css-loader识别 - 临时绕过:
@import 'antd/es/style/themes/index.less';—— 去掉~,依赖 Webpack 默认的node_modules查找逻辑(但会失去 alias 的灵活性)
Vite 中用 additionalData 注入变量文件时别名失效
Vite 的 CSS 插件虽捕获 .less 文件,但 additionalData 中的 @import 是由 Less 引擎运行时执行的,此时 Vite 别名机制已退出作用域。
- 错误写法:
additionalData: `@import "@/styles/variables.less";`—— 静默失败,HMR 不触发,变量undefined - 正确写法:
additionalData: `@import "${path.resolve(__dirname, 'src/styles/variables.less')}";`—— 必须用绝对路径 - 同时确认
lessOptions.javascriptEnabled: true已开启,否则@import不执行
真正容易被忽略的是:所有路径问题的本质不是“怎么写好看”,而是“谁在解析、在哪解析、按什么规则解析”。~ 不是语法糖,它是 Webpack 显式划分解析边界的信号;漏掉它,就等于把模块路径交给了文件系统——而文件系统根本不知道 @ 是什么。


















