Vite中commonjsOptions.include配置详解与优化
2026/8/5 9:15:19 网站建设 项目流程

1. 理解commonjsOptions.include的应用场景

在Vite项目的构建配置中,commonjsOptions.include参数常常让开发者感到困惑。这个配置项本质上是为了解决项目中混合使用ES模块和CommonJS模块时的兼容性问题。当你的项目依赖链中存在CommonJS格式的包时,Vite需要明确知道哪些模块需要被特殊处理。

常见需要配置include的情况包括:

  • 项目依赖的第三方库明确使用module.exports语法
  • 从旧版Node.js项目迁移过来的遗留代码
  • 使用了未正确声明模块类型的npm包
  • 需要处理动态require的复杂场景

2. 配置原理深度解析

2.1 Vite的模块处理机制

Vite在开发环境下使用浏览器原生ES模块,而在生产构建时默认使用Rollup打包。Rollup原生支持ES模块,但对CommonJS模块需要借助@rollup/plugin-commonjs进行转换。这个转换过程就是commonjsOptions配置发挥作用的地方。

include参数实际上是在告诉Rollup:"只有这些指定的模块需要被CommonJS插件处理"。这种定向处理的好处是:

  1. 避免对已经是ES模块的代码进行不必要的转换
  2. 减少构建时的处理开销
  3. 防止双重转换导致的奇怪问题

2.2 include的典型配置模式

在实际项目中,include通常配置为数组形式,支持以下几种匹配模式:

// vite.config.js export default { build: { commonjsOptions: { include: [ // 明确指定包名 'lodash', 'react-draggable', // 使用通配符匹配 'node_modules/react-*/**', // 正则表达式匹配 /node_modules\/.*cjs/, // 本地文件匹配 'src/legacy/**' ] } } }

3. 实战配置指南

3.1 何时必须配置include

以下情况必须显式配置include:

  1. 控制台出现"require is not defined"错误时
  2. 使用Vite插件如@vitejs/plugin-react时遇到模块加载问题
  3. 项目依赖树中包含未转译的CommonJS模块
  4. 需要优化构建性能,减少不必要的模块转换

3.2 配置的最佳实践

  1. 精确匹配优于模糊匹配:尽量指定具体的包名而非宽泛的通配符
  2. 逐步添加而非全部包含:通过构建错误提示逐步添加必要模块
  3. 性能考量:大型项目应该将常用CJS依赖预先配置
  4. 开发/生产环境差异:某些依赖可能只需要在生产环境转换
// 推荐的生产环境配置示例 export default { build: { commonjsOptions: { include: [ // 已知的CJS依赖 'react-dnd', 'react-draggable', 'lodash', // UI库的子组件 'antd/es/date-picker', // 本地遗留代码 'src/utils/legacy.js' ], exclude: ['node_modules/**.mjs'] // 明确排除ES模块 } } }

4. 常见问题排查

4.1 典型错误场景

  1. 未包含必要模块

    • 症状:运行时出现"require is not defined"
    • 解决:检查报错模块是否在include列表中
  2. 过度包含导致问题

    • 症状:ES模块被错误转换导致功能异常
    • 解决:缩小include范围或添加exclude
  3. 动态require问题

    • 症状:条件加载的模块未正确处理
    • 解决:确保动态路径在include通配范围内

4.2 调试技巧

  1. 使用vite --debug查看详细的模块转换日志
  2. 在rollupOptions中增加输出日志:
    plugins: [ commonjs({ include: [...], transformMixedEsModules: true, debug: true }) ]
  3. 检查最终产物的模块格式是否正确

5. 性能优化建议

合理的include配置可以显著提升构建性能:

  1. 基准测试:比较不同配置下的构建时间
  2. 依赖分析:使用npm ls查看完整的依赖树
  3. 渐进式优化
    • 初始阶段可以配置较宽泛的include
    • 根据构建日志逐步精确化配置
    • 最终锁定到具体的包和文件

对于大型项目,建议将commonjsOptions配置单独提取为文件,便于维护和团队共享:

// commonjs-deps.js module.exports = [ 'react-dnd', 'react-draggable', 'lodash', // 其他已知CJS依赖 ] // vite.config.js import cjsDeps from './commonjs-deps' export default { build: { commonjsOptions: { include: cjsDeps } } }

6. 与其他配置的协同

commonjsOptions.include需要与以下配置协同工作:

  1. optimizeDeps.include

    • 用于开发环境的预构建
    • 与build.commonjsOptions.include有部分重叠
  2. rollupOptions.external

    • 防止某些依赖被打包
    • 需要与include配置保持一致
  3. build.lib模式

    • 库模式需要更精确的模块控制
    • 通常需要更严格的include配置

一个综合配置示例:

export default { optimizeDeps: { include: ['react', 'react-dom'] // 开发环境预构建 }, build: { commonjsOptions: { include: ['react-dnd', 'lodash'], // 生产环境CJS转换 exclude: ['node_modules/**.mjs'] }, rollupOptions: { external: ['react'], // 外部化依赖 plugins: [ // 其他Rollup插件 ] } } }

7. 版本升级注意事项

随着Vite版本更新,commonjsOptions的行为可能有变化:

  1. Vite 3.x → 4.x

    • CommonJS转换策略更智能
    • 需要的显式配置可能减少
  2. Vite 4.x → 5.x

    • 对混合模块的支持更好
    • 但仍建议保留关键配置

升级后建议:

  1. 先移除所有include配置测试构建
  2. 根据报错逐步添加必要配置
  3. 比较新旧版本的构建产物差异

8. 项目迁移场景处理

从其他构建工具迁移到Vite时,需要特别注意:

  1. Webpack迁移

    • Webpack对CJS更宽容
    • 需要仔细检查所有非ESM依赖
  2. Parcel迁移

    • Parcel的自动转换可能掩盖问题
    • 需要显式声明所有CJS依赖
  3. UMD库集成

    • UMD通常需要作为CJS处理
    • 可能需要额外配置transformMixedEsModules

迁移检查清单:

  1. 运行构建并记录所有CJS相关警告
  2. 对每个警告分析是否需要添加到include
  3. 测试运行时行为是否与源构建一致

9. 高级应用场景

9.1 微前端集成

在微前端架构中,子应用可能使用不同的模块系统:

// 主应用配置 export default { build: { commonjsOptions: { include: [ // 子应用暴露的CJS模块 'micro-app-1/dist/entry.cjs', 'micro-app-2/dist/entry.js' ] } } }

9.2 条件性包含

根据环境变量动态调整include:

export default { build: { commonjsOptions: { include: [ 'lodash', ...(process.env.USE_LEGACY ? ['legacy-module'] : []) ] } } }

9.3 插件开发

开发Vite插件时处理CJS依赖:

export default function myPlugin() { return { name: 'my-plugin', config(config) { config.build.commonjsOptions.include = [ ...(config.build.commonjsOptions.include || []), 'my-plugin/deps' ] } } }

10. 工具链集成

10.1 与TypeScript配合

当使用TypeScript时,需要确保tsconfig.json的module设置与Vite配置一致:

// tsconfig.json { "compilerOptions": { "module": "ESNext", "moduleResolution": "node" } }

10.2 与ESLint配合

配置ESLint识别两种模块语法:

// .eslintrc.js module.exports = { rules: { 'import/no-commonjs': 'off' // 允许CJS语法 } }

10.3 与测试工具配合

测试环境可能需要不同的配置:

// vitest.config.js import { defineConfig } from 'vitest/config' import viteConfig from './vite.config' export default defineConfig({ ...viteConfig, test: { deps: { inline: ['react-dnd'] // 测试环境特殊处理 } } })

11. 长期维护建议

  1. 文档化配置决策:为每个include项添加注释说明原因
  2. 定期审查依赖:使用npm outdated检查依赖更新
  3. 建立自动化检查:在CI中添加模块格式验证
  4. 团队知识共享:记录常见问题的解决方案

配置文档示例:

/** * CommonJS模块包含配置 * * react-dnd: 2.x版本仍使用CJS * lodash: 兼容旧版导入方式 * legacy-module: 内部遗留代码,待重构 */ const commonjsIncludes = [ 'react-dnd', 'lodash', 'src/legacy/**' ]

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询