我在许多项目(如 React)中看到,他们使用
require()
有条件地重新导出属性,如下所示:
// index.js
if (process.env.NODE_ENV === 'production' {
exports = require('./cjs/react.production.min.js')
} else {
exports = require('./cjs/react.development.js')
}
我正在尝试将其转换为等效的有效 ES6 语法,保留单个导出的成员(用于树摇动)。
我已经尝试过了,它有效,但你无法导入个人成员:
import * as prod from './cjs/react.production.min.js'
import * as dev from './cjs/react.development.js'
let exports = {}
if (process.env.NODE_ENV === 'production') {
exports = prod
} else {
exports = dev
}
export default exports
是否有与使用有效 ES6 语法的原始版本等效的内容?
我想有了足够智能的编译器,嵌套模块中分配的键可以在构建时传播到顶层,如下所示:
import { value_1 as prod_value_1 } from './cjs/react.production.min.js'
import { value_1 as dev_value_1 } from './cjs/react.development.js'
let value_1 = undefined
if (process.env.NODE_ENV === 'production') {
value_1 = prod_value_1
} else {
value_1 = dev_value_1
}
export { value_1 /* value_2, etc */ }
将 CommonJS 中的条件
require()
语句转换为 ES6 语法,同时保留树摇动功能可能有点具有挑战性。您所描述的方法是正确的。但是,重要的是要了解 ES6 import
和 export
语句是静态的,不能在像 if
语句那样的条件块内使用。
您在问题后半部分描述的方法(导入单个成员然后有条件地分配它们)是处理此问题的一种方法。这是您的方法的扩展和稍微改进的版本:
import * as prod from './cjs/react.production.min.js';
import * as dev from './cjs/react.development.js';
let finalExports = {};
const keys = Object.keys(prod);
keys.forEach(key => {
finalExports[key] = process.env.NODE_ENV === 'production' ? prod[key] : dev[key];
});
// Explicitly export each member
export const {
Component1,
Component2,
// ... other exports
} = finalExports;
这种方法确实有一些缺点:
另一种方法是使用 Webpack 或 Rollup 等构建工具来处理特定于环境的捆绑。这些工具可以在构建过程中根据环境替换导入,从而实现更高效的树摇动和更小的包大小。这是一个使用 Webpack 的示例
DefinePlugin
:
// webpack.config.js
const webpack = require('webpack');
module.exports = {
// ... other webpack config
plugins: [
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV)
})
],
resolve: {
alias: {
'react': process.env.NODE_ENV === 'production'
? './cjs/react.production.min.js'
: './cjs/react.development.js'
}
}
};
在源代码中,您只需从“react”导入,Webpack 将根据环境将其替换为正确的文件。这种方法更易于维护并且更适合优化。