一篇文章带你从零快速上手Rollup

前言

项目中一直用的都是webpack,前一段需要开发几个类库供其他平台使用,本来打算继续用webpack的,但感觉webpack用来开发js库,不仅繁琐而且打包后的文件体积也比较大。正好之前看vue源码,知道vue也是通过rollup打包的。这次又是开发类库的,于是就快速上手了rollup。

本篇文章是我有了一定的项目实践后,回过来给大家分享一下如何从零快速上手rollup。

什么是rollup?

系统的了解rollup之前,我们先来简单了解下What is rollup?

关于rollup的介绍,官方文档已经写的很清楚了:

Rollup 是一个 JavaScript 模块打包器,可以将小块代码编译成大块复杂的代码,例如 library 或应用程序。

与Webpack偏向于应用打包的定位不同,rollup.js更专注于Javascript类库打包。

我们熟知的Vue、React等诸多知名框架或类库都是通过rollup.js进行打包的。

为什么是rollup?

webpack我相信做前端的同学大家都用过,那么为什么有些场景还要使用rollup呢?这里我简单对webpack和rollup做一个比较:
总体来说webpack和rollup在不同场景下,都能发挥自身优势作用。webpack对于代码分割和静态资源导入有着“先天优势”,并且支持热模块替换(HMR),而rollup并不支持。

所以当开发应用时可以优先选择webpack,但是rollup对于代码的Tree-shaking和ES6模块有着算法优势上的支持,若你项目只需要打包出一个简单的bundle包,并是基于ES6模块开发的,可以考虑使用rollup。

其实webpack从2.0开始就已经支持Tree-shaking,并在使用babel-loader的情况下还可以支持es6 module的打包。实际上,rollup已经在渐渐地失去了当初的优势了。但是它并没有被抛弃,反而因其简单的API、使用方式被许多库开发者青睐,如React、Vue等,都是使用rollup作为构建工具的。

快速上手

我们先花大概十分钟左右的时间来了解下rollup的基本使用以及完成一个hello world。

安装

首先全局安装rollup:

npm i rollup -g

目录准备(hello world)

接着,我们初始化一个如下所示的项目目录

├── dist # 编译结果
├── example # HTML引用例子
│   └── index.html
├── package.json
└── src # 源码
    └── index.js

首先我们在src/index.js中写入如下代码:

console.log("柯森");

然后在命令行执行以下命令:

rollup src/index.js -f umd -o dist/bundle.js

执行命令,我们即可在dist目录下生成bundle.js文件:

(function (factory) {
 typeof define === 'function' && define.amd ? define(factory) :
 factory();
}((function () { 'use strict';

 console.log("柯森");

})));

这时,我们再在example/index.html中引入上面打包生成的bundle.js文件,打开浏览器:

打包后的bundle.js仍然会在Node.js中工作,但是the-answer不包含在包中。为了解决这个问题,将我们编写的源码与依赖的第三方库进行合并,rollup.js为我们提供了resolve插件。

首先,安装resolve插件:

npm i -D @rollup/plugin-node-resolve

修改配置文件rollup.config.js:

import resolve from "@rollup/plugin-node-resolve";

export default {
 input: ["./src/index.js"],
 output: {
 file: "./dist/bundle.js",
 format: "umd",
 name: "experience",
 },
 plugins: [resolve()],
};

这时再次执行npm run build,可以发现报错已经没有了:

提示我们缺少@babel/core,因为@babel/core是babel的核心。我们来进行安装:

npm i @babel/core

再次执行打包,发现这次没有报错了,但是我们尝试打开dist/esBundle.js:

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

 const a = 1;
 const b = 2;
 console.log(a, b);
 var es6 = (() => {
 return a + b;
 });

 return es6;

})));

可以发现箭头函数仍然存在,显然这是不正确的,说明我们的babel插件没有起到作用。这是为什么呢?

原因是由于我们缺少.babelrc文件,添加该文件:

{
 "presets": [
 [
  "@babel/preset-env",
  {
  "modules": false,
  // "useBuiltIns": "usage"
  }
 ]
 ]
}

我们看.babelrc配置了preset env,所以先安装这个插件:

npm i @babel/preset-env

这次再次执行打包,我们打开dist/esBundle.js文件:

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

 var a = 1;
 var b = 2;
 console.log(a, b);
 var es6 = (function () {
 return a + b;
 });

 return es6;

})));

可以看到箭头函数被转换为了function,说明babel插件正常工作。

json插件

为什么要使用json插件?

在src目录下创建json.js文件:

import json from "../package.json";
console.log(json.author);

内容很简单,就是引入package.json,然后去打印author字段。

修改rollup.config.js配置文件:

import resolve from "@rollup/plugin-node-resolve";
import commonjs from "@rollup/plugin-commonjs";
import babel from "@rollup/plugin-babel";

export default {
 input: ["./src/json.js"],
 output: {
 file: "./dist/jsonBundle.js",
 format: "umd",
 name: "experience",
 },
 plugins: [resolve(), commonjs(), babel()],
 external: ["the-answer"],
};

执行打包,发现会发生如下报错:

提示我们缺少@rollup/plugin-json插件来支持json文件。

json插件的使用

来安装该插件:

npm i -D @rollup/plugin-json

同样修改下配置文件,将插件加入plugins数组即可。

然后再次打包,发现打包成功了,我们打开生成的dist/jsonBundle目录:

(function (factory) {
 typeof define === 'function' && define.amd ? define(factory) :
 factory();
}((function () { 'use strict';

 var name = "rollup-experience";
 var version = "1.0.0";
 var description = "";
 var main = "index.js";
 var directories = {
 example: "example"
 };
 var scripts = {
 build: "rollup -c -w",
 test: "echo \"Error: no test specified\" && exit 1"
 };
 var author = "Cosen";
 var license = "ISC";
 var dependencies = {
 "@babel/core": "^7.11.6",
 "@babel/preset-env": "^7.11.5",
 "the-answer": "^1.0.0"
 };
 var devDependencies = {
 "@rollup/plugin-babel": "^5.2.0",
 "@rollup/plugin-commonjs": "^15.0.0",
 "@rollup/plugin-json": "^4.1.0",
 "@rollup/plugin-node-resolve": "^9.0.0"
 };
 var json = {
 name: name,
 version: version,
 description: description,
 main: main,
 directories: directories,
 scripts: scripts,
 author: author,
 license: license,
 dependencies: dependencies,
 devDependencies: devDependencies
 };

 console.log(json.author);

})));

完美!!

tree-shaking机制

这里我们以最开始的src/index.js为例进行说明:

import answer from "the-answer";

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

修改上述文件:

const a = 1;
const b = 2;
export default function () {
 console.log(a + b);
}


执行打包。打开dist/bundle.js文件:

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

 var a = 1;
 var b = 2;
 function index () {
 console.log(a + b);
 }

 return index;

})));

再次修改src/index.js文件:

const a = 1;
const b = 2;
export default function () {
 console.log(a);
}

再次执行打包,打开打包文件:

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

 var a = 1;
 function index () {
 console.log(a);
 }

 return index;

})));

发现了什么?

我们发现关于变量b的定义没有了,因为源码中并没有用到这个变量。这就是ES模块著名的tree-shaking机制,它动态地清除没有被使用过的代码,使得代码更加精简,从而可以使得我们的类库获得更快的加载速度。

总结

本文大致向大家介绍了什么是rollup以及如何快速上手rollup。文中提到的这些其实只是冰山一角,rollup能玩的东西还有很多,关于更多可以去rollup 官网查询

到此这篇带你从零快速上手Rollup的文章就介绍到这了,更多相关从零快速上手Rollup内容请搜索来客网以前的文章或继续浏览下面的相关文章希望大家以后多多支持来客网!