[译] 同中有异的 Webpack 与 Rollup

本文讲的是[译] 同中有异的 Webpack 与 Rollup,


同中有异的 Webpack 与 Rollup



本周,Facebook 将一个非常大的 pull request 合并到了 React 主分支。这个 PR 将 React 当前使用的构建工具替换成了 Rollup。这让许多人感到不解,纷纷在推特上提问:“为什么你们选择 Rollup 而不选择 Webpack 呢?”1 2 3

有人问这个问题是很正常的。Webpack 是现在 JavaScript 社区中最伟大的成功传奇之一,它有着数百万/月的下载量,驱动了成千上万的网站与应用。它有着巨大的生态系统、众多的贡献者,并且它与一般的社区开源项目不同——它有着意义非凡的经济支持

相比之下,Rollup 是那么的微不足道。但是,除了 React 之外,Vue、Ember、Preact、D3、Three.js、Moment 等众多知名项目都使用了 Rollup。为什么会这样呢?为什么这些项目不使用大家一致认可的 JavaScript 模块打包工具呢?

这两个打包工具的优缺点

Webpack 由 Tobias Koppers 在 2012 年创建,用于解决当时的工具不能处理的问题:构建复杂的单页应用(SPA)。尤其是它的两个特点改变了一切:

  1. 代码分割可以将你的 app 分割成许多个容易管理的分块,这些分块能够在用户使用你的 app 时按需加载。这意味着你的用户可以有更快的交互体验。因为访问那些没有使用代码分割的应用时,必须要等待整个应用都被下载并解析完成。当然,你也可以自己手动去进行代码分割,但是……总之,祝你好运。
  2. 静态资源的导入:图片、CSS 等静态资源可以直接导入到你的 app 中,就和其它的模块、节点一样能够进行依赖管理。因此,我们再也不用小心翼翼地将各个静态文件放在特定的文件夹中,然后再去用脚本给文件 URL 加上哈希串了。Webpack 已经帮你完成了这一切。

而 Rollup 的开发理念则不同:它利用 ES2015 模块的巧妙设计,尽可能高效地构建精简且易分发的 JavaScript 库。而其它的模块打包器(包括 Webpack在内)都是通过将模块分别封装进函数中,然将这些函数通过能在浏览器中实现的 require 方法打包,最后依次处理这些函数。在你需要实现按需加载的时候,这种做法非常的方便,但是这样做引入了很多无关代码,比较浪费资源。当你有很多模块要打包的时候,这种情况会变得更糟糕

ES2015 模块则启用了一种不同的实现方法,Rollup 用的也就是这种方法。所有代码都将被放置在同一个地方,并且会在一起进行处理。因此得到的最终代码相较而言会更加的精简,运行起来自然也就更快。你可以点击这儿亲自试试 Rollup 交互式解释器(REPL)

但这儿也存在一些需要权衡的点:代码分割是一个很棘手的问题,而 Rollup 并不能做到这一点。同样的,Rollup 也不支持模块热替换(HMR)。而且对于打算使用 Rollup 的人来说,还有一个最大的痛点:它通过插件处理大多数 CommonJS 文件的时候,一些代码将无法被翻译为 ES2015。而与之相反,你可以把这一切的事全部放心交给 Webpack 去处理。

那么我到底应该选用哪一个呢?

到目前为止,我们已经清晰地了解了这两个工具共存并且相互支撑的原因 — 它们应用于不同的场景。那么,现在这个问题的答案简单来说就是:

在开发应用时使用 Webpack,开发库时使用 Rollup

当然这不是什么严格的规定——有很多的网站和 app 一样是使用 Rollup 构建的,同时也有很多的库使用 Webpack。不过,这是个很值得参考的经验之谈。

如果你需要进行代码分割,或者你有很多的静态资源,再或者你做的东西深度依赖 CommonJS,毫无疑问 Webpack 是你的最佳选择。如果你的代码基于 ES2015 模块编写,并且你做的东西是准备给他人使用的,你或许可以考虑使用 Rollup。

对于包作者的建议:请使用 pkg.module

在很长一段时间里,使用 JavaScript 库是一件有点风险的事,因为这意味着你必须和库的作者在模块系统上的意见保持一致。如果你使用 Browserify 而他更喜欢 AMD,你就不得不在 build 之前先强行将两者粘起来。通用模块定义(UMD)格式对这个问题进行了 部分 的修复,但是它没有强制要求在任何场景下都使用它,因此你无法预料你将会遇到什么坑。

ES2015 改变了这一切,因为 import 与 export 就是语言规范本身的一部分。在未来,不再会有现在这种模棱两可的情况,所有东西都将更加无缝地配合工作。不幸的是,由于大多数浏览器和 Node 还不支持 import 和 export,我们仍然需要依靠 UMD 规范(如果你只写 Node 的话也可以用 CommonJS)。

现在给你的库的 package.json 文件增加一个 "module": "dist/my-library.es.js" 入口,可以让你的库同时支持 UMD 与 ES2015。这很重要,因为 Webpack 和 Rollup 都使用了pkg.module 来尽可能的生成效率更高的代码——在一些情况下,它们都能使用 tree-shake 来精简掉你的库中未使用的部分。

了解更多有关 pkg.module 的内容请访问 Rollup wiki 。

希望这篇文章能让你理清这两个开源项目之间的关系。如果你还有问题,可以在推特联系rich_harrisrollupjsthelarkinn。祝你打包快乐!

感谢 Rich Harris 写了这篇文章。我们坚信开源协作是共同促进 web 技术前进的重要动力。

没有时间为开源项目做贡献?想要以其它方式回馈吗?欢迎通过 Open Collective 进行捐赠,成为 Webpack 的支持者或赞助商。Open Collective 不仅会资助核心团队,而且还会资助那些贡献出空闲时间帮助我们改进项目的贡献者们。





原文发布时间为:2017年4月12日


本文来自合作伙伴掘金,了解相关信息可以关注掘金网站。

时间: 2024-09-13 11:05:06

[译] 同中有异的 Webpack 与 Rollup的相关文章

[译] Swift 中关于并发的一切:第一部分 — 当前

本文讲的是[译] Swift 中关于并发的一切:第一部分 - 当前, 原文地址:All about Concurrency in Swift - Part 1: The Present 原文作者:Umberto Raimondi 译文出自:掘金翻译计划 译者:Deepmissea 校对者:Feximin,zhangqippp Swift 中关于并发的一切:第一部分 - 当前 在 Swift 语言的当前版本中,并没有像其他现代语言如 Go 或 Rust 一样,包含任何原生的并发功能. 如果你计划异

[译] Xcode 中的用户断点

本文讲的是[译] Xcode 中的用户断点, 原文地址:User Breakpoints in Xcode 原文作者:Michael Ochs 译文出自:掘金翻译计划 本文永久链接:github.com/xitu/gold-m- 译者:oOatuo 校对者:fengzhihao123, LeviDing Xcode 中的用户断点 大家应该都用过 Xcode 中的断点,但你们熟悉用户断点么?下面我将向你们介绍如何使用以及何时使用这种断点.如果你已经对用户断点有所了解了,可以查看下文章后面的清单,看

[译]Swift 中的通用数据源

本文讲的是[译]Swift 中的通用数据源, 原文地址:Generic Data Sources in Swift 原文作者:Andrea Prearo 译文出自:掘金翻译计划 本文永久链接:github.com/xitu/gold-m- 译者:Swants 校对者:iOSleep Swift 中的通用数据源 在我开发的绝大多数 iOS app 中, tableView 和 collectionView 绝对是最常用的 UI 组件.鉴于设置一个 tableView 或 collectionVie

[译] ES6+ 中的 JavaScript 工厂函数(第八部分)

本文讲的是[译] ES6+ 中的 JavaScript 工厂函数(第八部分), 原文地址:JavaScript Factory Functions with ES6+ 原文作者:Eric Elliott 译文出自:掘金翻译计划 本文永久链接:github.com/xitu/gold-m- 译者:lampui 校对者:IridescentMia.sunui Smoke Art Cubes to Smoke - MattysFlicks - (CC BY 2.0) 注意:这是"软件编写"系

[译] Javascript 中多样的 this

本文讲的是[译] Javascript 中多样的 this, 原文地址:The many faces of this in javascript 原文作者:Michał Witkowski 译文出自:掘金翻译计划 本文永久链接:github.com/xitu/gold-m- 译者:lsvih 校对者:lampui, zerosrat 本文将尽量解释清楚 JavaScript 中最基础的部分之一:执行上下文(execution context).如果你经常使用 JS 框架,那理解 this 更是锦

[译] RxJava 中的错误处理

本文讲的是[译] RxJava 中的错误处理, 原文地址:Error handling in RxJava 原文作者:Dmitry Ryadnenko 译文出自:掘金翻译计划 本文永久链接:github.com/xitu/gold-m- 译者:星辰 校对者:张拭心 Liz Drawing 一旦你开始使用 RxJava 函数库写代码,你会发现一些东西能有很多不同的实现方式,但是有时你很难立即确定哪种方法最好,错误处理就是其中之一. 那么,在 RxJava 中处理错误的最佳方法是什么,又有哪些选择呢

[译] 代码中添加注释之好坏丑

本文讲的是[译] 代码中添加注释之好坏丑, 原文地址:Putting comments in code: the good, the bad, and the ugly. 原文作者:Bill Sourour 译文出自:掘金翻译计划 译者: bambooom 校对者:zhangqippp.steinliber 代码中添加注释之好坏丑 题图是克林特 · 伊斯特伍德在<黄金三镖客>中剧照. 如果你以前听过这句话就打断我... 「好的代码自身就是文档」. 在我 20 多年以写代码为生的经历中,这是我听

[译] JavaScript 中的 CSS:基于组件的样式的未来

本文讲的是[译] JavaScript 中的 CSS:基于组件的样式的未来, 原文地址:CSS in JavaScript: The future of component-based styling 原文作者:Jonathan Z. White 译文出自:掘金翻译计划 译者:bambooom 校对者:Aladdin-ADD.reid3290 JavaScript 中的 CSS:基于组件的样式的未来 使用行内样式使我们可以获得 JavaScript 的所有编程支持.这让我们获得类似 CSS 预处

SQLServer中汇总功能的使用GROUPING,ROLLUP和CUBE

第一次看到这样的SQL语句,看不懂,其中用到了下面的不常用的 聚集函数:GROUPING 用于汇总数据用的运算符: ROLLUP SELECT CASE GROUPING(o.customerid) WHEN 0 THEN o.customerid ELSE  '(Total)' END AS AllCustomersSummary, CASE GROUPING(od.orderid) WHEN 0 THEN od.orderid ELSE -1 END AS IndividualCustome