阿夸漫谈

Webpack vs Rollup

发表于 2019-03-05

提起前端构建工具,首先想到就是 Webpack,目前 vue-cli、create-react-app 等知名脚手架都是默认采用 Webpack 作为构建工具。Webpack 凭其完善的生态、强大的功能,成为前端构建工具的首选。Rollup 虽然没 Webpack 有名,但在 react、vue、D3 等知名库中却普遍使用,那两者到底有什么区别,让我们一探究竟。

1. 起源


Webpack 创建于 2012 年,目前 webpack4 已发布,webpack5 也即将发布。Webpack 的目的主要是为了解决在模块化开发下,打包困难的问题。相比于早期的 gulp、grunt 等构建工具,Webpack 凭其代码分割、按需加载等特点一统江湖。

Rollup 也是一个模块打包工具。和 Webpack 不同的是,Rollup 是将各个模块打包进一个包中,在打包过程中通过 Tree-shaking 特性来静态分析代码中的 import ,删除项目中未使用的代码,使打包后的大小尽可能小。

2. 实战


现在我们写个简单的项目,然后分别用 Webpack 和 Rollup 进行打包,观察两者区别。

2.1 创建项目

安装相关依赖,全局安装或者项目中局部安装:

npm install webpack webpack-cli rollup --global

新建模块入口 src/main.js:

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

入口文件引用的 hello.js 模块:

// src/hello.js
let a = 1; // 无用代码
export default 'hello world!';

2.2 Webpack 打包

首先我们先用 Webpack 进行打包,终端在项目目录下执行:

webpack src/main.js --mode=development

得到打包后结果:

 (function(modules) { // webpackBootstrap
    /*...*/
 })({
    "./src/hello.js": (function(module, __webpack_exports__, __webpack_require__) {
        "use strict";
        eval("__webpack_require__.r(__webpack_exports__);\nlet a = 1; // 无用代码\r\n\r\n/* harmony default export */ __webpack_exports__[\"default\"] = ('hello world!');\r\n\n\n//# sourceURL=webpack:///./src/hello.js?");
    }),
    "./src/main.js": (function(module, __webpack_exports__, __webpack_require__) {
        "use strict";
        eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _hello_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./hello.js */ \"./src/hello.js\");\n// src/main.js\r\n\r\n\r\n/* harmony default export */ __webpack_exports__[\"default\"] = (function () {\r\n  console.log(_hello_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"]);\r\n});\n\n//# sourceURL=webpack:///./src/main.js?");
    })
});

可以看出打包后的文件实际上就是一个立即执行函数,这个立即执行函数接收一个参数,这个参数是模块对象,键为各个模块的路径,值为模块内容。立即执行函数内部则处理模块之间的引用,执行模块等。

Webpack 打包后默认使用 CommonJS 模块规范。打包后的文件,相对于原本分模块时的代码多了很多,因为 Webpack 根据 CommonJS 模块规范对模块进行包装,并在自执行函数内部实现了按需加载等特性。

2.3 Rollup 打包

用 Rollup 进行打包,终端在项目目录下执行:

rollup src/main.js -f cjs

得到打包后结果:

'use strict';

var hello = 'hello world!';

// src/main.js
function main () {
  console.log(hello);
}
module.exports = main;

可以看出 Rollup 打包后的大小远小于 Webpack 打包后的大小,Rollup 就是将各个模块打包进一个文件中,并且通过 Tree-shaking 来删除无用的代码,像 hello.js 模块中的无用代码就被删除了。

3. 总结


通过上面的实战可以看出 Rollup 打包后的大小远小于 Webpack 打包后的大小,但 Rollup 不支持很多高级功能,比如代码分割、按需加载等。除此之外,webpack2 的时候新增了 Tree-shaking 的特性,所以构建项目中需要这些高级功能的时候,我们应该选择 Webpack;而构建库的时候,我们通常希望打包成一个文件,且文件尽可能小,此时我们就应该选择 Rollup。

(完)

目录