如何打包保留ES2015模块特性的JavaScript类库
原生JavaScript方案打包ES模块为单个可导入文件
首先,你想要把多个ES2015模块合并成单个文件,同时保留ES模块特性(让用户能通过import导入),这个需求完全可以用原生Node.js脚本实现,不需要第三方打包工具。下面分两种场景给你解决方案:
一、简单场景:聚合导出 + 手动合并(适合少量模块)
如果你的类库只有几个模块,最快的方式是先创建一个聚合导出模块,再把所有模块内容合并到一个文件里:
- 创建一个入口模块
magic-lib.js,负责导入所有子模块并重新导出:
// magic-lib.js import Foo from './foo.js'; import Bar from './bar.js'; // 导出Foo作为默认导出,同时导出Bar作为命名导出 export { Foo as default, Bar };
- 手动把
foo.js、bar.js和magic-lib.js的内容合并到一个新文件dist/magic-lib.js里,注意要去掉子模块里的export default,改成普通类定义,最后保留聚合导出的语句:
// dist/magic-lib.js // 来自foo.js的内容 class Foo { // 你的Foo类代码 } // 来自bar.js的内容 class Bar { // 你的Bar类代码 } // 聚合导出 export { Foo as default, Bar };
这样用户就能直接在自己的ES模块中使用:
// using-magic-lib.js import Foo from './dist/magic-lib.js'; import { Bar } from './dist/magic-lib.js'; // 正常使用Foo和Bar
二、自动化方案:用Node.js脚本批量打包(适合多模块场景)
如果模块数量多,手动合并太麻烦,可以写一个简单的Node.js脚本自动处理依赖并合并所有模块:
- 创建打包脚本
bundle.js:
const fs = require('fs').promises; const path = require('path'); // 递归解析模块及其依赖 async function resolveModule(modulePath, moduleCache = new Map()) { if (moduleCache.has(modulePath)) return moduleCache.get(modulePath); const fullPath = path.resolve(modulePath); const content = await fs.readFile(fullPath, 'utf8'); // 处理相对路径的import语句(仅匹配import ... from './xxx.js'格式) const processedContent = content.replace( /import\s+(.*?)\s+from\s+['"](\.\/.*?)['"]/g, async (match, _, relativePath) => { const depPath = path.join(path.dirname(fullPath), relativePath); // 先递归处理依赖模块 await resolveModule(depPath, moduleCache); // 合并时不需要保留内部import,直接替换为空 return ''; } ); moduleCache.set(modulePath, processedContent); return processedContent; } // 主打包函数 async function bundle(entryFile, outputFile) { const moduleCache = new Map(); // 解析入口模块及其所有依赖 await resolveModule(entryFile, moduleCache); // 合并所有模块内容 const mergedContent = Array.from(moduleCache.values()).join('\n\n'); // 加上最终的导出语句(根据你的需求调整) const exportStmt = ` export { Foo as default, Bar }; `; // 写入输出文件 await fs.writeFile(outputFile, mergedContent + exportStmt, 'utf8'); console.log(`✅ 打包完成,输出文件:${outputFile}`); } // 执行打包:入口是我们的聚合模块,输出到dist/magic-lib.js bundle('./magic-lib.js', './dist/magic-lib.js');
- 执行脚本:在终端运行
node bundle.js,脚本会自动把foo.js、bar.js和magic-lib.js的内容合并成单个dist/magic-lib.js文件,并且保留ES模块导出特性。
补充:关于Rollup的小提示
你之前用Rollup没得到预期结果,大概率是配置问题。如果之后想尝试Rollup,只要把输出格式设置为es就能保留ES模块特性,比如rollup.config.js:
export default { input: './magic-lib.js', output: { file: './dist/magic-lib.js', format: 'es' // 关键:输出ES模块格式 } };
内容的提问来源于stack exchange,提问作者treeno
相关产品推荐
相关产品推荐

