Rollup

随着前端的复杂性,工程化、组件化、模块化已经成为项目的必需品,而这些目标的实现都需要工具来帮助开发者完成,目前最流程的几大构建工具中,常用的有Webpack和Rollup

Rollup被成为下一代模块打包器,可对es6模块编写的程序友好地打包。开发者可以将项目拆分成多个小文件,从而降低代码复杂度,消除不可预知的相互影响,减少出错率。而Roolup可以将多个小文件打包输出为一个最终文件。
Rollup一般用于库程序或部分应用程序。因为Rollup还不支持一些特定的高级功能,比如:code-splitting,dynamic imports,此时可以使用Webpack。

1. 特性

ES6
Rollup可以直接使用ES6的语法,通过import``export管理模块,替代了原来Commonjs和AMD的require方式
Tree-shaking
对代码静态分析,仅打包输出实际用到的代码。这样可以大大降低输出文件的大小。

// foo.js
export function getName() { console.log('lisa') }
export function getSex() { console.log('female') }

// main.js
import { getName } from './foo'
function main() {
  getName()
}

以上cjs打包输出则只输出引用到的函数

'use strict';

function getName() {
  console.log('Lisa');
}

function main () {
  getName();
}

module.exports = main;

多格式
Roolup可以提供多种输出格式,方便兼容Commonjs,ES6模块等。可到官网REPL查看编译后的各种输出格式的区别

/* DEFAULT EXPORTS
   Default exports from the 'entry module' are
   exported from the bundle */
import answer from './answer.js';

export default function () {
    console.log( 'the answer is ' + answer );

// answer.js
export default 42;
}
  • cjs: nodejs格式
'use strict';

var answer = 42;

/* DEFAULT EXPORTS
   Default exports from the 'entry module' are
   exported from the bundle */

function main () {
    console.log( 'the answer is ' + answer );
}

module.exports = main;
  • esm: ES6格式
var answer = 42;

/* DEFAULT EXPORTS
   Default exports from the 'entry module' are
   exported from the bundle */

function main () {
    console.log( 'the answer is ' + answer );
}

export default main;
  • iife: 原生立即执行函数
var myBundle = (function () {
   'use strict';

   var answer = 42;

   /* DEFAULT EXPORTS
      Default exports from the 'entry module' are
      exported from the bundle */

   function main () {
    console.log( 'the answer is ' + answer );
   }

   return main;

}());
  • umd: 多环境兼容
(function (global, factory) {
   typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
   typeof define === 'function' && define.amd ? define(factory) :
   (global = global || self, global.myBundle = factory());
}(this, (function () { 'use strict';

   var answer = 42;

   /* DEFAULT EXPORTS
      Default exports from the 'entry module' are
      exported from the bundle */

   function main () {
    console.log( 'the answer is ' + answer );
   }

   return main;
})));

2. 构建脚本

2.1 构建
安装

npm install rollup --global # or `npm i rollup -g` for short

创建脚本

// main.js
import foo from './foo.js';
export default function () {
  console.log(foo);
}

// foo.js
export default 'hello world'

构建

rollup main.js -f cjs -o bundle.js

输出文件

'use strict';

var foo = 'hello world!';

function main () {
  console.log(foo);
}

module.exports = main;

2.2 命令行参数
详见官网命令行参数

-i, --input                 要打包的文件(必须)
-o, --output.file           输出的文件 (如果没有这个参数,则直接输出到控制台)
-f, --output.format [es]    输出的文件类型 (amd, cjs, es, iife, umd)
-e, --external              将模块ID的逗号分隔列表排除
-g, --globals               以`module ID:Global` 键值对的形式,用逗号分隔开 
                              任何定义在这里模块ID定义添加到外部依赖
-h, --help                    打印帮助文档
-n, --name                  生成UMD模块的名字
-m, --sourcemap             生成 sourcemap (`-m inline` for inline map)
-v,--version            打印安装的Rollup版本号
-w,--watchc             监听源文件。若有改动,则重新打包
--amd.id                    AMD模块的ID,默认是个匿名函数
--amd.define                使用Function来代替`define`
--no-strict                 在生成的包中省略`"use strict";`
--no-conflict               对于UMD模块来说,给全局变量生成一个无冲突的方法
--intro                     在打包好的文件的块的内部(wrapper内部)的最顶部插入一段内容
--outro                     在打包好的文件的块的内部(wrapper内部)的最底部插入一段内容
--banner                    在打包好的文件的块的外部(wrapper外部)的最顶部插入一段内容
--footer                    在打包好的文件的块的外部(wrapper外部)的最底部插入一段内容
--interop                   包含公共的模块(这个选项是默认添加的)
--slient                     不要将警告打印到控制台

3. 配置文件及参数

实际开发更多使用配置文件。配置的核心功能:input,output, plugins, 分别指定了 输入、输出、处理各类文件的插件
3.1 配置文件
创建rollup.config.js文件,配置打包参数

export default {
  input: "main.js",
  output: {
     file: 'bundle.js',
     format: 'cjs'
  }
}

输出多个文件格式

export default {
  input: "main.js",
  output: [{
     file: 'dist/bundle.js',
     format: 'cjs'
  }, {
     file: 'dist/umd.js',
     format: 'umd',
     name: 'myBundleName'  // 用于输出时将函数定义绑定到该全局变量上,参见下面输出文件内容
  }]
}

打包

rollup -c

输出文件内容

// bundle.js
'use strict';

var foo = 'hello world!';

function main () {
  console.log(foo);
}

module.exports = main;

// umd.js
(function (global, factory) {
  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
  typeof define === 'function' && define.amd ? define(factory) :
  (global = global || self, global.myBundleName = factory());
}(this, (function () { 'use strict';

  var foo = 'hello world!';

  function main () {
    console.log(foo);
  }

  return main;

})));

3.2 配置参数
具体说明见https://www.rollupjs.com/guide/big-list-of-options/

// rollup.config.js
export default {
  // 核心选项
  input,     // 必须
  external,
  plugins,

  // 额外选项
  onwarn,

  // danger zone
  acorn,
  context,
  moduleContext,
  legacy

  output: {  // 必须 (如果要输出多个,可以是一个数组)
    // 核心选项
    file,    // 必须
    format,  // 必须
    name, // UMD格式时必须

    globals,

    // 额外选项
    paths,
    banner,
    footer,
    intro,
    outro,
    sourcemap,
    sourcemapFile,
    interop,

    // 高危选项
    exports,
    amd,
    indent
    strict
  },
};

4. 插件

一些非JS文件或高级JS处理需要插件来扩展打包功能, 如:JSON文件,Babel编译、alias设置等。可用插件列表见这里

安装插件

npm install --save-dev rollup-plugin-json

代码

import { version } from '../package.json'

export default function() {
  console.log('version' + version)
}

配置文件

// rollup.config.js
import json from 'rollup-plugin-json';

export default {
  input: 'src/main.js',
  output: {
    file: 'bundle.js',
    format: 'cjs'
  },
  plugins: [ json() ]
};

·rollup -c·后输出

'use strict';

var version = "1.0.0";

var main = function () {
  console.log('version ' + version);
};

module.exports = main;

通过tree-shaking,仅输出引入的 version字段

Rollup API

Rollup提供了JavaScript API,可以在Nodejs中使用,用于扩展Rollpup

  • rollup.rollup()
    用于在Nodejs中扩展或定制打包流程
    输入参数: input options
    返回类型:Promise对象,解析一个bundle对象,此对象包含一些属性和方法(generate(), write()),见如下示例
const rollup = require('rollup');

// see below for details on the options
const inputOptions = {...};
const outputOptions = {...};

async function build() {
  // create a bundle
  const bundle = await rollup.rollup(inputOptions);

  console.log(bundle.imports); // an array of external dependencies
  console.log(bundle.exports); // an array of names exported by the entry point
  console.log(bundle.modules); // an array of module objects

  // generate code and a sourcemap
  const { code, map } = await bundle.generate(outputOptions);

  // or write the bundle to disk
  await bundle.write(outputOptions);
}

build();
  • rollup.watch()
    监控文件的改变,重构文件。一般用于Nodejs定制开发模式下启动项目,和express结合相当于实现了web-dev-server
const rollup = require('rollup');

const watchOptions = {...};
const watcher = rollup.watch(watchOptions);

watcher.on('event', event => {
  // event.code 会是下面其中一个:
  //   START        — 监听器正在启动(重启)
  //   BUNDLE_START — 构建单个文件束
  //   BUNDLE_END   — 完成文件束构建
  //   END          — 完成所有文件束构建
  //   ERROR        — 构建时遇到错误
  //   FATAL        — 遇到无可修复的错误
});

// 停止监听
watcher.close();

参考文章

  1. https://www.rollupjs.org/
  2. //www.greatytc.com/p/3e8941eda2dd
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,384评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,845评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,148评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,640评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,731评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,712评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,703评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,473评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,915评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,227评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,384评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,063评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,706评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,302评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,531评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,321评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,248评论 2 352