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
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。