You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何打包保留ES2015模块特性的JavaScript类库

原生JavaScript方案打包ES模块为单个可导入文件

首先,你想要把多个ES2015模块合并成单个文件,同时保留ES模块特性(让用户能通过import导入),这个需求完全可以用原生Node.js脚本实现,不需要第三方打包工具。下面分两种场景给你解决方案:

一、简单场景:聚合导出 + 手动合并(适合少量模块)

如果你的类库只有几个模块,最快的方式是先创建一个聚合导出模块,再把所有模块内容合并到一个文件里:

  1. 创建一个入口模块magic-lib.js,负责导入所有子模块并重新导出:
// magic-lib.js
import Foo from './foo.js';
import Bar from './bar.js';

// 导出Foo作为默认导出,同时导出Bar作为命名导出
export { Foo as default, Bar };
  1. 手动把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脚本自动处理依赖并合并所有模块:

  1. 创建打包脚本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');
  1. 执行脚本:在终端运行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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 06:52:51