
ES 模块不支持运行时动态 import() 之外的条件加载,但可通过预导入 + 条件赋值方式实现环境感知的默认导出,兼顾静态分析与构建工具优化。
es 模块不支持运行时动态 `import()` 之外的条件加载,但可通过预导入 + 条件赋值方式实现环境感知的默认导出,兼顾静态分析与构建工具优化。
在从 CommonJS 迁移至 ES 模块(ESM)时,一个常见痛点是:无法像 module.exports = require('./env') 那样在顶层直接做条件导入。这是因为 ESM 的 import 语句必须是静态声明(位于模块顶层、不可被条件包裹),而 require() 是动态的 CommonJS 行为。
✅ 正确做法是:预先静态导入所有可能用到的模块,再通过逻辑判断选择导出目标。例如:
// config/index.js import Production from './prod.js'; import Development from './dev.js'; const defaultExport = process.env.NODE_ENV === 'production' ? Production : Development; export default defaultExport;
⚠️ 注意事项:
- 所有 import 必须位于文件顶层(不可放在 if 内),否则会触发语法错误;
- process.env.NODE_ENV 在纯前端 ESM 环境中默认不可用——需依赖打包工具(如 Vite、Webpack、esbuild)进行环境变量注入(例如 Vite 中通过 import.meta.env.PROD 更安全);
- 若需更严格的构建时分支(彻底排除未使用模块),应配合 import.meta.env.PROD(Vite)或 process.env.NODE_ENV === 'production'(Webpack DefinePlugin)实现 tree-shaking 友好的写法:
// 推荐:利用构建工具常量替换,实现真正的条件编译
if (import.meta.env.PROD) {
export { default as default } from './prod.js';
} else {
export { default as default } from './dev.js';
}
该写法在 Vite 中会被自动转换为 export { default as default } from './prod.js'(生产构建),并剔除 dev.js 的引用,显著减小包体积。
总结:ES 模块强调静态结构,动态行为需交由构建层或运行时逻辑兜底。优先使用构建时环境常量(如 import.meta.env.PROD)替代 process.env.NODE_ENV,既保证类型安全,又利于优化与调试。










