如何配置Webpack同时输出CommonJS与ESM格式构建产物
问题说明
使用Webpack构建面向服务端应用的TypeScript库时,需要同时生成CommonJS与ESM两种格式的构建产物,直接给output字段传入数组的方式无法达到预期。当前单格式构建的配置如下:
const path = require("path"); module.exports = { entry: "./src/index.ts", devtool: "inline-source-map", module: { rules: [ { test: /\.tsx?$/, use: "ts-loader", exclude: /node_modules/, }, ], }, resolve: { extensions: [".tsx", ".ts", ".js"], }, output: { filename: "index.cjs", path: path.resolve(__dirname, "dist"), chunkFormat: 'commonjs', } };
实现方法
Webpack原生不支持在单个配置对象内通过给output传数组生成多格式产物,需要使用多配置模式:导出一个由多个配置对象组成的数组,每个对象对应一种格式的构建规则,通用的loader、resolve、entry等配置可以抽离复用。
调整后的完整可用配置:
const path = require("path"); // 抽离两种构建格式共享的基础配置 const sharedConfig = { entry: "./src/index.ts", devtool: "inline-source-map", module: { rules: [ { test: /\.tsx?$/, use: "ts-loader", exclude: /node_modules/, }, ], }, resolve: { extensions: [".tsx", ".ts", ".js"], }, target: "node", // 适配服务端Node.js环境,避免打包内置Node模块 }; module.exports = [ // CommonJS 产物配置 { ...sharedConfig, output: { filename: "index.cjs", path: path.resolve(__dirname, "dist"), chunkFormat: "commonjs", library: { type: "commonjs2", }, }, }, // ESM 产物配置 { ...sharedConfig, output: { filename: "index.mjs", path: path.resolve(__dirname, "dist"), chunkFormat: "module", library: { type: "module", }, }, // Webpack输出ESM格式必须开启该实验特性 experiments: { outputModule: true, }, }, ];
配置说明
- 执行常规构建命令时,Webpack会自动遍历配置数组,依次完成两种格式的打包,无需多次执行构建指令
- ESM构建必须开启
experiments.outputModule: true,否则构建过程会抛出格式不支持的错误 - 两种格式的
chunkFormat和library.type需要和产物格式匹配,避免出现模块运行兼容问题 - 配置
target: "node"适配服务端运行环境,Webpack会自动跳过Node.js内置模块的打包,减小产物体积
内容的提问来源于stack exchange,提问作者Huakun Shen
相关产品推荐
相关产品推荐

