Webpack 和 Rollup 的区别

最近被问到一个这样的问题:Webpack 和 Rollup 有什么区别?

说实话我觉得这种问题挺无聊的,Webpack 和 Rollup 都是 Web 前端界的打包工具,无非就是通过一堆插件对资源进行处理,最后生成对应的产物,用于部署或者第三方使用。

要我用文字描述出他们的细节差异似乎并不是一件简单的事情。一般来说,我们更倾向于用 Rollup 打包纯 JavaScript 的库(library),而用 Webpack 来打包资源更复杂的应用。

机缘巧合之下,看到了一篇 Rollup 作者写的文章,介绍了一些他们更深层次的区别。

目标

Webpack 创建于 2012 年,先于 Rollup 出现,他的目标是解决单页面应用(SPA)的打包问题。

当时我们还在使用 grunt、gulp 等打包工具纯手动地对各类资源进行处理。Webpack 的两大亮点给我们的打包流程带来了巨大的改变:1. 代码拆分,把太大的代码包拆成多个小文件,按需异步加载;2. 静态资源的 import,我们不用再区分各类资源,不管是 CSS 还是图片资源,都只需要 import 进来,让 Webpack 的 loader 去处理即可,最终 Webpack 会生成对应的 js、css、图片等文件,并处理好他们的路径关系。

这样只需要指定 JavaScript 的入口文件,就可以轻松地打包所有用到的资源。

Rollup 出现得晚一些,它的目标是打包 ESM,生成高效的代码。

模块的处理

Rollup 的目标就是生成更高效的代码,所以它会把所有的 ESM 都集中到一个 scope 中来,打包后的文件看上去就是一个大的 JavaScript 文件,而不会有各种 function 的嵌套。

这样的好处是代码更简洁,重复代码少,执行速度也更快;坏处则是难以支持代码拆分,因此也难以实现模块热更新(HMR)。

Webpack 就不一样了,它的目标是处理所有的资源,简单起见,它会把每个资源都处理成一个模块,最后导出成一个 function,然后不同模块引用的时候调用这个 function 即可。

这样的结果是打包后的文件里面会有很多模板代码,各种 function 的嵌套,运行时占用更多的内存,性能也是有所下降的。

Webpack 从 v3 开始也支持了 scope hoisting,但是因为它支持的资源种类繁多,有很多情况限制了 scope hoisting 的发挥,具体可以查看相关文档

所以,从结果来看,Rollup 生成的代码依然是更简洁更高效的,而 Webpack 则更强大,可以处理各种类型的资源。

如何选择

Rollup 作者给出了一个非常简单的选择方案:用 Webpack 打包应用,而用 Rollup 打包库。

当然这个方案并不是绝对的,我们也有用 Rollup 打包应用的例子,可以参考 Svelte 的官方示例。

具体来说,就是当你有代码拆分、静态资源处理的需求时,选择 Webpack 更简单;而产出第三方库供他人使用时,不妨使用 Rollup 来生成更高效更简洁的代码。


© 2021