需显式安装 less 和 less-loader 作为 devDependencies,并将 javascriptEnabled 等配置移至 lessOptions 对象内;同时确保 rules 中 exclude 正确排除 .less 文件、use 顺序正确、paths 或 alias 配置使 ~ 别名在 Less 中生效。

Webpack 5 报 Cannot find module 'less' 怎么办
这不是配置写错了,是 less 包根本没装——less-loader 只是“调度员”,不带编译器。Webpack 5 不再隐式 fallback 到全局或父级 node_modules,必须显式安装为 devDependencies。
- 运行
npm list less less-loader,如果显示empty或MISSING,立刻执行:npm install --save-dev less less-loader - 别信某些文档只说装
less-loader就够了,less@4.2.0+是当前 Webpack 5 最稳的版本,less-loader@8.3.0是配套推荐版 - 装完后删掉
node_modules和package-lock.json,重装一遍,避免peer dep解析错乱
less-loader 配置里 javascriptEnabled 报错
Webpack 5 + less-loader@7+ 已废弃顶层 javascriptEnabled: true,直接写会触发 Invalid options object。Ant Design 等库的 Less 文件大量依赖内联 JS(比如 .bezierEasingMixin()),不启用就解析失败。
- 旧写法(Webpack 4 / less-loader@5):
{ javascriptEnabled: true }—— 现在无效 - 新写法(Webpack 5+ / less-loader@7+):
{ lessOptions: { javascriptEnabled: true } } - 如果用了
modifyVars,也得包进lessOptions里:{ lessOptions: { javascriptEnabled: true, modifyVars: { '@primary-color': '#1890ff' } } }
Webpack 5 的 rules 顺序和 exclude 冲突导致 .less 被当成资源文件
常见现象是编译不报错,但最终 CSS 里全是 src_abc123.css 这种 hash 路径,样式全丢——本质是 file-loader 或 url-loader 的 exclude 没拦住 .less,把它当普通资源输出了,less-loader 根本没机会处理。
- 检查所有
rules中的exclude正则,确保包含less,例如:exclude: /\.(js|jsx|ts|tsx|json|css|less)$/ -
use数组顺序是倒序执行,正确链路必须是:['style-loader', 'css-loader', { loader: 'less-loader', options: { lessOptions: { javascriptEnabled: true } } }] - 如果用了
css-loader的importLoaders,要确认它指向的是less-loader层级,比如importLoaders: 2表示往前数两层(less-loader→css-loader)
@import '~antd/...' 报路径找不到,不是文件缺失
~ 是 Webpack 的模块解析别名,但 less-loader 默认不走 Webpack 的 resolve.alias,所以 @import '~antd/es/style/themes/index.less' 会直接失败,尤其在 antd@5.x 中该路径已彻底移除。
立即学习“前端免费学习笔记(深入)”;
- 最稳方案:在
less-loader的lessOptions里加paths:{ lessOptions: { paths: [path.resolve(__dirname, 'node_modules')] } } - 或者配 Webpack alias:
resolve: { alias: { '~antd': path.resolve(__dirname, 'node_modules/antd') } },再配合lessOptions.paths双保险 - 临时绕过:删掉
~,写成@import 'antd/es/style/themes/default.less',靠 Webpack 默认 node_modules 查找逻辑兜底(仅限 antd@4.x)
真正卡住人的地方往往不在报错信息本身,而在构建链路中多个 loader 对同一文件的“抢夺”——.less 被谁先拿到、是否被 exclude 拦截、lessOptions 是否被正确透传、~ 别名是否穿透到了 Less 解析器内部。每一步都得单独验证,不能只看最终错误堆栈。


















