Vite构建核心在于理解“不打包、只按需编译”逻辑,精准干预预构建、模块解析与Rollup流程,并用函数式配置适配多场景。

精通 Vite 构建不是靠堆砌配置,而是理解它“不打包、只按需编译”的底层逻辑,并围绕这个核心做精准干预。重点不在写得多,而在改得准——改对预构建、改对模块解析、改对构建流程的边界点。
吃透依赖预构建机制
Vite 启动快的关键是 esbuild 对 node_modules 里第三方包的预构建(转成 ESM 并缓存到 node_modules/.vite)。但默认行为有时会出问题:
- 遇到未导出
exports字段或含动态require的包(如某些旧版工具库),预构建可能失败或跳过,导致运行时报错 - 预构建结果被缓存后,升级依赖却不清理缓存,会沿用旧版本的转换结果
解决方法:
- 在
vite.config.js中显式指定需强制预构建的包:optimizeDeps.include: ['lodash-es', 'date-fns'] - 排除干扰项:
optimizeDeps.exclude: ['some-legacy-cjs-lib'],让 Vite 直接以原始方式处理(配合插件如@originjs/vite-plugin-commonjs) - 开发中怀疑缓存异常时,直接删掉
node_modules/.vite目录再启动
精准控制模块解析与别名
别名不只是为了少敲几个 ../../..,更是为了切断错误路径、统一模块来源、避免重复实例:
- 用
resolve.alias把@指向src是基础;更进一步,可将vue显式 alias 到vue/dist/vue.esm-bundler.js,确保开发与生产使用同一构建版本 - 对多环境共用的工具函数,用
resolve.dedupe: ['lodash-es', 'mitt']防止同一包因路径不同被多次加载 - 禁用自动解析
package.json#exports字段(仅调试用):resolve.conditions = ['import'],避免某些包的条件导出逻辑干扰 HMR
构建阶段深度干预 Rollup 流程
Vite 生产构建本质是封装好的 Rollup,但默认隐藏了大量细节。要真正掌控输出,必须进到 build.rollupOptions 层:
- 手动配置
output.manualChunks拆分第三方包(如把vue、vue-router、pinia单独抽成vendor),比默认的commonjs分块更可控 - 启用
build.sourcemap: 'hidden':生成 sourcemap 但不注入到产物中,兼顾调试与安全 - 用
build.rollupOptions.plugins插入自定义 Rollup 插件(如rollup-plugin-visualizer分析包体积,或rollup-plugin-replace注入构建时间戳)
用配置函数应对多场景切换
一个项目常需适配 dev / preview / build、dev / test / prod 等多种组合。硬写多个配置文件太重,推荐用函数式配置:
- 根据
command区分开发与构建逻辑:if (command === 'build') { return { build: { minify: 'terser' } } } - 结合
mode加载不同环境变量:loadEnv(mode, process.cwd(), ''),再注入到define或plugins - 异步读取配置(如从远程 CMS 获取构建参数):
export default defineConfig(async () => { const config = await fetchConfig(); return { ... } })
不复杂但容易忽略











