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

如何用Rollup.js构建类似d3的全局闭包对象?

嘿,我完全懂你想要的效果——把零散的工具函数、原型扩展和闭包打包成一个像D3那样的全局对象myClos,直接通过script标签引入后就能全局调用对吧?我之前做过类似的配置,给你一步步拆解实现方法:

第一步:初始化Rollup项目并安装依赖

首先得把Rollup的环境搭起来,打开终端执行这些命令:

# 初始化npm项目(一路回车就行)
npm init -y

# 安装Rollup核心和必要插件
npm install rollup @rollup/plugin-node-resolve @rollup/plugin-commonjs --save-dev

# 可选:安装代码压缩插件,生产环境用
npm install @rollup/plugin-terser --save-dev

第二步:整理你的模块结构

把你的代码按功能拆分成不同的ES模块文件,比如这样的目录结构:

your-project/
├── src/
│   ├── index.js          # 入口文件,用来整合所有模块
│   ├── helpers.js        # 工具函数集合
│   ├── prototypes.js     # 原型扩展代码
│   └── closures.js       # 闭包相关的代码
├── rollup.config.js      # Rollup配置文件
└── package.json

举几个模块的例子:

  • helpers.js:导出你的工具函数
// src/helpers.js
export function helper1() {
  console.log('执行helper1');
  // 这里可以直接用全局的d3,比如d3.select('body')
}

export function helper2(data) {
  return d3.max(data); // 依赖全局的d3对象
}
  • closures.js:导出闭包生成的对象
// src/closures.js
export const counter = (function() {
  let privateCount = 0;

  return {
    increment() {
      privateCount++;
      return privateCount;
    },
    reset() {
      privateCount = 0;
    }
  };
})();
  • prototypes.js:直接执行原型扩展代码(不需要导出)
// src/prototypes.js
// 扩展Array的自定义方法
Array.prototype.myFilter = function(callback) {
  const result = [];
  for (let i = 0; i < this.length; i++) {
    if (callback(this[i], i, this)) {
      result.push(this[i]);
    }
  }
  return result;
};
  • index.js:整合所有模块,导出最终的myClos对象
// src/index.js
// 导入工具函数
import * as helpers from './helpers.js';
// 导入闭包对象
import { counter } from './closures.js';
// 引入原型扩展(不需要赋值,直接执行)
import './prototypes.js';

// 构建全局要暴露的对象
const myClos = {
  ...helpers, // 展开所有工具函数
  counter     // 添加闭包对象
};

// 导出这个对象,Rollup会把它挂载到全局
export default myClos;

第三步:配置Rollup的打包规则

在项目根目录创建rollup.config.js,关键配置是输出格式为iife(立即执行函数表达式),并指定全局对象名myClos:

// rollup.config.js
import resolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
import terser from '@rollup/plugin-terser';

export default {
  // 入口文件就是我们的src/index.js
  input: 'src/index.js',
  output: {
    // 打包后的输出文件路径
    file: 'dist/myClos.min.js',
    // 格式选iife,生成立即执行函数,自动挂载到window
    format: 'iife',
    // 全局对象的名字,就是你要的myClos
    name: 'myClos',
    // 如果依赖全局的d3,告诉Rollup直接用window.d3,不要打包进去
    globals: {
      d3: 'd3'
    }
  },
  // 把d3标记为外部依赖,不打包到你的文件里(假设你已经通过script引入了d3)
  external: ['d3'],
  plugins: [
    resolve(), // 解析ES模块的导入路径
    commonjs(), // 如果你的代码里有CommonJS格式的模块,转成ES模块
    terser() // 压缩代码,生产环境用,开发环境可以注释掉
  ]
};

第四步:添加打包命令并执行

打开package.json,在scripts里加一条打包命令:

{
  "scripts": {
    "build": "rollup -c"
  }
}

然后在终端执行:

npm run build

执行完后,dist/myClos.min.js就是打包好的文件了。

最后:在HTML里使用

像引入D3一样引入你的打包文件,就能全局调用myClos了:

<!-- 先引入D3 -->
<script src="https://d3js.org/d3.v7.min.js"></script>
<!-- 再引入你的myClos -->
<script src="dist/myClos.min.js"></script>

<script>
  // 全局调用测试
  myClos.helper1(); // 输出"执行helper1"
  console.log(myClos.helper2([2,4,6])); // 输出6
  console.log(myClos.counter.increment()); // 输出1
  console.log([1,2,3,4].myFilter(num => num > 2)); // 输出[3,4]
</script>

一些额外提示

  • 如果你的代码没有依赖外部模块(比如不需要D3),可以删掉external和globals配置项
  • 开发的时候可以去掉terser插件,让打包后的代码更易读
  • 如果有更多模块,只需要在index.js里导入并添加到myClos对象即可

内容的提问来源于stack exchange,提问作者SumNeuron

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 06:40:06