如何用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
相关产品推荐
相关产品推荐

