Webpack 和 Rollup :一样但又不同

10年服务1亿前端开发工程师

小编推荐:掘金是一个面向程序员的高质量技术社区,从 一线大厂经验分享到前端开发最佳实践,无论是入门还是进阶,来掘金你不会错过前端开发的任何一个技术干货。

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) 使你可以将应用程序分解成可管理的代码块,可以按需加载,这意味着你的用户可以快速获取交互性的网站,而不必等到整个应用程序下载和解析完成。当然你可以手动来完成这项工作,那么祝你好运。
  2. 静态资源(Static assets) 如图像和 CSS 可以导入到你的应用程序中,而且还能够被作为依赖图中的另一个节点。再也不用关心你的文件是否放在正确的文件夹中,再也不用为文件 URL 增添 hash 而使用 hack 脚本,因为 webpack 会帮我们处理这些事情。

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 。

给NPM包作者的建议:请使用 pkg.module !

在很长一段时间内,使用 JavaScript 库需要一些投机取巧,这是因为你和库作者使用的模块系统可能不一样,所以这就需要你和库作者在模块系统的选择上必须达成一致意见。举个例子,假设你使用的是Browserify打包工具,但是库作者更喜欢AMD模块系统,所以在你构建之前,你必须把库作者的模块系统替换成自己项目所使用的模块系统。虽然通用模块定义(UMD)格式类型固定,但是因为它没有在任何地方被要求强制执行,你永远不知道你下一步使用的模块系统是哪一种。

ES2015 改变了所有这一切,因为 importexport 是 JavaScript 语言的一部分。在将来,不会有歧义,模块系统会更加无缝地对接。不幸的是,因为浏览器(大多数)以及 Node 不支持 importexport ,我们仍然需要 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

希望这篇文章能使两个打包工具之间的关系更加清晰。如果你仍然还有问题,你可以通过这些Twitter账号 rich_harris、rollupjs、thelarkinn 找到我们。让我们一起快乐的打包吧!

推荐阅读

JavaScript 模块简史
ECMAScript 6 Modules(模块)系统及语法详解
webpack 中文文档(v3.3.0)
使用 webpack 3 构建高性能的应用程序
webpack 2 入门
为 Progressive Web App 提供的 Webpack 加载器和插件
webpack 2中的Tree Shaking

原文链接:https://medium.com/webpack/webpack-and-rollup-the-same-but-different-a41ad427058c

赞(1) 打赏
未经允许不得转载:WEB前端开发 » Webpack 和 Rollup :一样但又不同

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏