根本原因是构建工具未将跨组件共用的基础样式识别为同一模块;Vite 默认不合并懒加载组件中重复 import 的 CSS,因其按 JS chunk 切分逻辑处理,且路径不一致或未显式归一化时 Rollup 无法去重。

根本原因不是“拆分”本身,而是构建工具没把跨组件共用的基础样式识别为同一模块——它看到 import './Button.css' 在 3 个懒加载组件里各出现一次,就默认打包 3 份。
为什么 Vite 默认不合并重复 import 的 CSS?
Vite 的 CSS 去重只在开发阶段靠浏览器 URL 缓存生效(import './base.css' 写十次,浏览器只发一次请求),但构建时会按 JS chunk 切分逻辑走:每个异步组件生成独立 chunk,若它们各自 import 了相同路径的 CSS 文件,且该路径未被 manualChunks 显式归一,Rollup 就可能把它复制进多个 chunk。
-
build.cssCodeSplit = true(Vite 4.0+ 默认)只对「非动态导入中直接 import 的 CSS」生效,而懒加载组件内部的import属于动态上下文 - 如果 CSS 文件路径不完全一致(比如
./styles/button.cssvs../assets/button.css),Rollup 视为不同模块,无法 dedupe - PostCSS 插件(如
postcss-import)若开启@import内联,反而会让重复内容在编译期固化,更难剥离
如何让多个懒加载组件共享同一份基础 CSS?
核心是把公共样式“提前锚定”,不让它跟着 JS chunk 跑。关键操作在 vite.config.ts 中配置 manualChunks:
- 把所有基础样式路径统一收口到
src/assets/styles/,并在main.ts或app.vue中一次性import,这样它们天然进入主 chunk - 若必须分散在组件内引入,则显式声明:
build: { rollupOptions: { output: { manualChunks: { styles: ['src/assets/styles/', /node_modules\/.*(?:sass|css|less)/i] } } } } - 禁用 UI 库的按需样式导入(如
element-plus/es/components/button/style/css),改用全量样式入口 +unplugin-element-plus自动注入,避免手动 import 触发多点打包
怎么验证是不是真重复了?
别信文件大小或直觉,看构建产物和 sourcemap:
立即学习“前端免费学习笔记(深入)”;
- 打开
.dist/目录,搜索Button.css对应的内容字符串(比如background-color: #007bff),看是否出现在多个.css文件里 - 用
source-map-explorer分析 CSS chunk 构成:npx source-map-explorer dist/assets/*.css - 检查浏览器 Network 面板:同一 CSS 内容是否以不同 hash 后缀(如
button.abc123.css和button.def456.css)被加载两次
真正容易被忽略的是路径归一化——哪怕只是多了一个 ./ 或少了一个 index.css 后缀,Rollup 就不会合并。动手前先 grep 所有 import.*\.css,确保路径完全一致。


















