问题的根源在于生产环境中的 CSS 提取策略、Less 变量注入时机以及样式加载顺序三者相互影响,最终导致 Less 编译结果与运行时实际生效的 CSS 不一致:css.extract:true 会强制执行全量提取,打断原有的按需编译流程;modifyVars 无法覆盖全部构建阶段;异步组件的样式加载顺序也可能失去控制;再加上系统路径、BOM、换行符等差异,会进一步放大构建环境和本地环境样式不一致的问题。

因此,核心原因并不是 Less 本身存在问题,而是生产构建环境与本地开发环境在 CSS 抽离、变量注入时机、样式执行顺序等方面叠加后,造成最终页面应用的 CSS 与 Less 编译预期出现偏差,这也是为什么 CSS 使用 Less 后构建环境和本地环境样式不同的关键所在。
css.extract: true 强制全量提取破坏按需编译链路
在 Vite 开发环境中, 通常会先编译,再以内联方式注入 JS,并通过 injectStyle 动态插入页面;而在生产环境开启 css.extract: true 后,所有 Less 文件会被统一收集、合并并压缩为独立的 .css 文件。这个过程会带来几个容易被忽视的问题:
- 原本基于组件模块触发的按需编译(例如只处理
Button.vue内的样式)会变成全量扫描,导致@import依赖关系可能提前解析,甚至重复解析 modifyVars注入的变量(例如@env: 'production')会在提取阶段被固化,但如果多个入口文件或异步 chunk 共用同一变量定义,就可能因为注入时机不同,造成条件分支样式判断错位
modifyVars 未穿透到所有构建阶段
vite.config.ts 中的 css.preprocessorOptions.less.modifyVars 只会在 Less 预处理阶段生效,但并不是所有样式资源都会经过这一层,因此常常出现本地正常、构建后异常的情况:
- 放在
public/目录下的.less文件不会被 Vite 编译处理,而是直接复制输出,因此完全不会经过modifyVars - 通过
additionalData注入的全局变量(如@import "vars.less";),如果路径配置错误或文件内容存在语法问题,开发环境通常会明显报错,但生产构建时有可能被静默跳过,最终导致变量回退到默认值 - 如果构建时使用了
--mode staging,但.env.staging中没有把VITE_ENV正确传递给modifyVars,那么 Less 中类似if(@env = 'staging')的判断将始终为false
异步组件样式加载顺序失控
在 Vue 或 React 中,如果通过 defineAsyncComponent 或 lazy() 加载异步组件,那么这些组件里的 在生产环境通常会被打包进异步 chunk 对应的 CSS 文件中。但在最终页面渲染时,HTML 里的 插入顺序并不一定能保证早于主 CSS,这就容易引发样式覆盖异常:
- 浏览器会并行请求多个
.css文件,在没有明确优先级控制的前提下,样式往往按照网络响应先后顺序生效 - 如果主包 CSS 中包含全局重置规则(例如
* { box-sizing: border-box; }),而异步 CSS 先一步加载完成,就可能在短时间内出现布局抖动或样式错乱 - Vite 默认不会为异步 chunk 对应的 CSS 自动添加
rel="preload"或media="print" onload="this.media='all'"之类的加载控制方案,因此顺序问题更难稳定保障
Windows 与 Linux 路径/BOM/换行符差异放大环境不一致
这类系统层面的差异在本地开发时往往不容易被发现,但一旦进入 CI/CD 或服务器构建环境,就很容易暴露出问题:
@import "mixinsvariables.less";(反斜杠)在 Windows 编辑器中看似正常,但 Less 解析器会把它当作普通字面量字符串处理,最终无法正确找到文件;规范写法必须统一为正斜杠:@import "mixins/variables.less";- Windows 记事本保存的
.less文件常常带有 UTF-8 BOM(EF BB BF),而 Linux 环境下的lessc4.x+ 可能直接报错:parse error: unrecognised input;可在 VSCode 右下角编码设置中选择 “Sa ve with Encoding → UTF-8” 去除 BOM - Windows 默认使用 CRLF 换行符,Linux/macOS 则使用 LF;某些插件(如
less-plugin-clean-css)对换行格式较为敏感,可能导致输出 CSS 的空行、缩进乃至属性顺序发生细微变化
真正麻烦的地方在于,这些问题彼此独立,但一旦叠加出现,现象就会非常分散,例如按钮颜色突然变蓝、间距异常、@primary-color 被原样输出等,排查时很难第一时间定位到具体原因。要解决“为什么 CSS 使用 Less 后构建环境和本地环境样式不同”这一问题,通常需要逐项核查:变量注入是否成功、CSS 是否按预期拆分、异步样式是否晚于重置规则加载,以及构建机器上的文件编码和换行格式是否一致。任何一个环节遗漏,都可能让“本地一切正常”演变为上线后的样式事故。
