开门见山
2017年4月初,Facebook 将一个 巨大的 pull 请求 合并到了 React 主分支(master) 中,将其现有的构建流程替换为基于 Rollup ,
这一举动 促使 一些人发很疑惑 “你为什么选择 Rollup 而抛弃 webpack ”?
这是一个完全合理的问题。Webpack 是现代 JavaScript 社区最成功的故事之一,每月有数百万的下载量,为成千上万的网站和应用提供支持
。它有一个庞大的生态系统,许多贡献者,而且作为一个社区开源项目,还有一个 有意义的财务支持 。
相比之下,Rollup 并不起眼。但 React 并不孤单 – Vue,Ember,Preact,D3,Three.js,Moment 以及其他许多知名的库也使用 Rollup
世界到底怎么了?为什么我们不能只有一个大众认可的 JavaScript 模块化打包工具?
关于这两个打包工具的故事
Webpack 始于2012年,由 Tobias Koppers发起,用于解决当时现有工具未解决的的一个难题:
构建复杂的单页应用程序(SPA)。特别是 webpack 的两个特性改变了一切:
1、代码拆分(Code Splitting) 使你可以将应用程序分解成可管理的代码块,可以按需加载,这意味着你的用户可以快速获取交互性的网站,
而不必等到整个应用程序下载和解析完成。当然你可以手动来完成这项工作,那么祝你好运。
静态资源(Static assets) 如图像和 CSS 可以导入到你的应用程序中,而且还能够被作为依赖图中的另一个节点。
再也不用关心你的文件是否放在正确的文件夹中,再也不用为文件 URL 增添 hash 而使用 hack 脚本,因为 webpack 会帮我们处理这些事情
2、Rollup 则是由于不同的原因被创建的:利用 ES2015 巧妙的模块设计,尽可能高效地构建出能够直接被其它 JavaScript 库引用的模块
其他的模块打包工具 – 包含 webpack – 通过都是将每个模块封装在一个函数中,
将它们放在一个包中,通过浏览器友好的 require 实现,最后逐一执行这些模块。
如果您需要按需加载,webpack 这类的打包工具非常合适。否则有点浪费,如果你有很多模块,它会变得更糟。
ES2015模块启用了一种不同的方法,这是真是 Rollup 使用的。所有的代码都放在同一个地方,然后一次性执行
,从而生成更简洁、更简单的代码,从而启动更快。您可以 自己使用 Rollup REPL 来查看它 。
但是有一个权衡:代码拆分(Code Splitting)是一个更加棘手的问题,在撰写本文时,Rollup 还不支持。
同样的,Rollup 也不支持模块的热更新(HMR)。
而对于使用 Rollup 的人来说,最大的痛点可能是 – 它能处理大多数 CommonJS 文件(通过 插件 ),
然而有些东西根本不能转译为 ES2015 ,而 webpack 能处理所有你丢给它的事情。
到底该怎么选择
到目前为止,希望这两个工具共同存在并相互支持的原因已经很明确了 – 它们有着不同的用途。总结一句话就是:
对于应用使用 webpack,对于类库使用 Rollup
这不是一个绝对的规则 – 事实上有许多 网站 和 应用程序使用 Rollup 构建,同样的也有大量的库使用了 webpack 构建。
但是,对于应用使用 webpack,对于类库使用 Rollup 是一个很好的经验法则。
如果你需要代码拆分(Code Splitting),或者你有很多静态资源需要处理,再或者你构建的项目需要引入很多CommonJS模块的依赖,
那么 webpack 是个很不错的选择。如果您的代码库是基于 ES2015 模块的,而且希望你写的代码能够被其他人直接使用,
你需要的打包工具可能是 Rollup 。
开发建议
在很长一段时间内,使用 JavaScript 库需要一些投机取巧,这是因为你和库作者使用的模块系统可能不一样,
所以这就需要你和库作者在模块系统的选择上必须达成一致意见。举个例子,假设你使用的是Browserify打包工具,
但是库作者更喜欢AMD模块系统,所以在你构建之前,你必须把库作者的模块系统替换成自己项目所使用的模块系统。
虽然通用模块定义(UMD)格式类型固定,但是因为它没有在任何地方被要求强制执行,你永远不知道你下一步使用的模块系统是哪一种。
ES2015 改变了所有这一切,因为 import 和 export 是 JavaScript 语言的一部分。在将来,不会有歧义,模块系统会更加无缝地对接。
不幸的是,因为浏览器(大多数)以及 Node 不支持 import 和 export ,
我们仍然需要 UMD 模块系统过渡(如果你构建的文件只是用于Node,或许可以考虑CommonJS)。
通过在您项目的 package.json 文件(又称 pkg.module)中添加 "module": "dist/my-library.es.js" 入口选项,
就可以同时为 UMD 和 ES2015 提供服务。
这很重要,因为 Webpack 和 Rollup 都可以使用 pkg.module 来尽可能构建出高效代码 –
在某些情况下,Webpack 以及 Rollup 甚至都能利用 tree-shake 特性来剔除项目中未使用的代码。
要想了解更多关于 pkg.module 的信息,请查看 Rollup wiki 。
希望这篇文章能使两个打包工具之间的关系更加清晰
谢谢观看,如有不足,敬请指教