新一代构建工具比较

333 阅读14分钟

原文地址:css-tricks.com/comparing-t…/

近年来,许多新的开发工具出现了,并且他们紧随着在前些年主导前端开发的工具,包括 webpack、 babel、rollup、parcel、create-react-app。

这些新的工具在设计上并不是具有相同的功能的,它们每一个都有想实现的不一样的东西。除去它们的差异外,这些工具都有着同一个目标:提高开发者的开发体验。

在这篇文章中,我会去评估每一个工具,概括它们的功能,为什么我们需要它们,以及它们的用法。我认为比较并不总是公平的。因此,在这篇文章中我们看到的也不是直接的比较。事实上, Snowpack 和 Vite 在某些任务上都是使用的 esbuild。我们的目标更多的是希望通过以一种更好的视角去看待这些让我们开发更加便捷的工具。通过这种方式,我们可以知道摆在我们面前有哪些选项以及它们是如何成型的,这样当我们需要使用它们时才能做出最好的选择。

当然,以下的内容都是基于我使用 React 和 Preact 的经历。因为相比之下,我更熟悉这些库,但是我们也会去看看它们对其他前端框架的支持情况。

为什么这些工具都出现在现在?

一部分原因我想是因为对 JavaScript 工具疲劳的反应——在这篇文章中提到过:回到2016学习JavaScript。它们也填补了编写一个 Vanilla JS 文件,以及在编写一行自己的代码之前不得不去下载 200MB 大小工具依赖的缺失中间地带。它们开箱即用且没有其他依赖项,这是 JavaScript 生态系统的趋势之一。

Snowpack,Vite 和 wmr 都是通过在浏览器中运行原生的 JS 模块。回到 2018 年,firefox 60 默认支持 ES Module(ESM)。自从那时起,所有的主流浏览器就都支持 ESM 了。Node.js 也在 2019 年的 11 月随原生 JS 模块一起发布。我们仍在寻找原生 JS 模块在 2021 年被发掘的可能性。

这些工具和现有的工具有什么差异?

不管我们是使用 webpack,Rollup 还是 Parcel 作为一个开发服务器,这些工具都会从我们的源代码和 node_modules 目录下打包我们的整个代码库,并经过一些构建的步骤,例如 Babel、TypeScript 或者 PostCSS,然后把这些打包好的代码发送给浏览器。这些都需要工作量,并且在更大型的代码库中,即使经过了缓存和优化开发服务器的速度仍会变得更慢。

Snowpack,Vite 和 wmr 开发服务器没有遵循这种模型。相反的,他们是等到浏览器找到一个 import的声明并发起一个 HTTP 请求时才返回相应的模块。只有请求被发起时,这些工具才会转换这些被请求的模块或者是模块引入树中的任意子节点,然后把这些发送给浏览器。这大大的提高了效率,因为在推送到开发服务器的过程中工作量更少了。

你会注意到 esbuild 没有出现在我们刚刚的讨论中,但实际上它是打包工具中最先也是最重要的。它不像其他工具那样回避打包。相反的,esbuild 通过避免昂贵的转换、利用并行处理和使用 Go 语言来快速的处理代码。

体验

在这篇文章中我会用不同的工具来重新构建 React 文档上的一个示例应用。这是原始仓库的链接,和4种构建工具测试的源代码链接,每一个使用的都是不同的构建工具。我们将会对比每一个构建步骤的产物。重新构建这个示例的应用让我能够测试出开发者将一些十分标准的React依赖引入到工具中的体验,包括 React Router 和 axios。

可比较的特性

在我们深入了解每一个工具的特性之前,它们每一个都支持以下开箱即用的特性:

  • 很好的支持原生 JS 模块
  • TS 编译(但不是类型检查)
  • JSX
  • 插件 API 的可扩展性
  • 内置开发服务器
  • CSS 打包,支持 CSS-in-JS 库

即使有类型错误,这些工具都能将 TS 编译成 JS。为了正确的进行类型检查,你应该去安装TS并在你的根 JS 文件中跑下tsc --noEmit 命令,或者使用编辑器的插件来帮你检查类型。

接下来让我们来看下每一个工具吧。

esbuild

esbuild 的作者是 Figma 的 CTO Evan Wallace。它的主要特点是它提供了比以 Node 为基础的打包器要快 10-100 倍的构建速度。它没有像 create-react-app 那样为开发者提供许多便利的东西。但是有越来越多的 esbuild 使用者出来填补这些空白,包括create-react-app-esbuildestrellaSnowpack,它们使用esbuild来作为它们的构建步骤。

esbuild 还非常的年轻,它还没有发行它的 1.0 版本,并且它也还没有准备好在生产环境中使用——但这相信已经不远了。它提供直观的 JS 和带有智能默认值的命令行 API。

esbuild 在打包工具的世界里是一个游戏规则的改变者。在大型的代码库中,esbuild 和 node 打包工具之间的速度差异会成倍增加。当 esbuild 发布 1.0 时,它将在大型生产的网站中非常有用,并且将会大量节省团队等待构建完成的时间。不幸的是,大型生产网站不得不去等待直到 esbuild 变的更稳定。同时,它同样会加速你的子项目构建速度。

esbuild 快如闪电的速度对于你现在在做的任何工作都将会成为一种便利。更少的时间去等待构建对于开发者而言一向是最好的体验。考虑到这一点,如果你正在对你的应用进行设计,你可能会希望从比esbuild 更高级的东西开始,否则,你将不得不去花费一些时间去引入依赖和搭建你的开发环境,然后才能享受到如我们所期望的JS生态中的便利。此外,如果你想要去尽可能的精简包体积大小,那么你可能还需要 Rollup 和 terser,它们能够稍微的减小包体积。

esbuild
多种前端框架的模板
模块热更新开发服务器
Streaming Imports(按需获取imported package)
预配置的生产构建
自动化的 postcss 和预处理器转换
HTML 转换
支持 Rollup 插件
默认安装的大小7.34MB

esbuild 是一个十分强大的工具。但是如果你习惯了零配置设置,它可能会难以上手。如果你需要更多,那么你可能需要看下一个使用了 esbuild 的工具——Snowpack。

Snowpack

Snowpack 的作者是 Skypack 和 Pika。它提供了令人惊叹的开发服务器,并且也是遵循“无构建开发”的想法被创作出来的。引用下文档中的介绍:“你去使用一个打包工具因为你想要使用而不是你需要使用”。

默认情况下,Snowpack 的构建步骤不是把所有文件打包到一个包中而是提供了能够在浏览器中运行的未打包的es模块。esbuild 实际上是作为了一个依赖存在的,但是 Snowpack 仅在使用 JS 模块和需要时使用 esbuild。

Snowpack 有一些十分有用的文档,包含了一系列如何将它与JS框架来一起使用的指南,还有一堆的模板。事实上,我第一次听说 Snowpack 是在 2020年 Svelte 峰会上 Rich Harris 的“未来网络开发”的演讲中。他在演讲中说到,即将发布的 Svelte 框架 SvelteKit 将会以 Snowpack 作为支撑,虽然后来改用了 Vite。

如果你想要在非打包构建部署上有更好的效果,那么 Snowpack 是一个很好的选择。你可能正编写着包含少量模块的源代码,这意味着你不会使用非打包构建创建一个大型的请求流。如果你不需要增加构建上的额外复杂度和技术债务,那么 Snowpack 是一个很好的选择。一个好的用例将会是你将前端框架逐步采用到服务端渲染或者是静态应用中。你将从 node 生态系统中获取尽可能少的工具,但是你仍然能够得到声明式的前端框架的好处。

此外,我认为 Snowpack 是使用 esbuild 的一个很好的示范。如果你想要尝试 esbuild 但是也想要一个开发服务器和一个预置的前端框架模板,那么 Snowpack 会是你不想错过的。在 Snowpack 配置的构建步骤中启用 esbuild,然后你就可以很好的使用了。

照目前的情况看,我认为 Snowpack 还不能成为像 create-react-app 这样的零配置工具的最好替代品,因为如果你有一个很大的应用程序,并且需要一个非常厉害的优化生产构建步骤,你需要自己去获取插件并配置它们。

Snowpack 通过功能齐全的开发服务器,详细的文档和易于安装的模板提供了轻量级的开发体验。剩下的交给你来决定是否要去打包你的应用程序和怎么去做。如果你想要一个同时提供开发服务器和一个更少配置化的构建步骤的工具,那可能需要去看下一个我们将会说到的工具——Vite。

Snowpack
多种前端框架的模板
模块热更新开发服务器✅(当使用模板的时)
Streaming Imports(按需获取imported package)
预配置的生产构建
自动化的 postcss 和预处理器转换
HTML 转换
支持 Rollup 插件✅(当在构建步骤中使用snowpack-plugin-rollup-bundle时)
默认安装的大小16MB

Vite

Vite 的作者也是 Vue 的作者尤小右。esbuild 专注于构建步骤,Snowpack 专注于开发服务器,Vite 则同时提供了这两者:完整的开发服务器和使用 Rollup 的优化构建命令。

如果你想要一个 create-react-app 或者是 Vue CLI 的对手,那么我想 Vite 会是最接近的一个,因为它自带了许多开箱即用的特性。极速启动的开发服务器和零配置的优化生产构建意味着你无需任何配置就可以从零到生产。Vite 是一个既能够被使用在小型项目,也可以用于大型产物应用程序的工具。一个好的 Vite 用例是任何的大型单页应用。

你为什么不使用 Vite ?Vite 是一个固执己见的工具,而且你可能会不同意它的意见。你可能不想在你的构建中使用 Rollup(我们已经讨论过 esbuild 在构建上是有多快),或者是你可能想要你的工具给你在 Babel,eslint 和 webpack loaders的生态系统中更多的权利。

此外,如果你想要零配置的服务端渲染框架,你最好继续使用以 webpack 为基础的框架,像是 Nuxt.js 和 Next.js,直到 Vite 的服务端渲染更加完善。

Vite 固执己见的天性使得它成为目前工具中十分强劲的竞争对手。许多工作 Vite 已经完成了,这使得开发体验真正无缝,并且使得生产就绪的构建开箱即用。

Vite
多种前端框架的模板
模块热更新开发服务器✅(当使用模板的时)
Streaming Imports(按需获取imported package)
预配置的生产构建
自动化的 postcss 和预处理器转换
HTML转换
支持 Rollup 插件
默认安装的大小17.1MB

wmr

和 Vite 一样,wmr 是另一个固执己见的构建工具。它同样提供了开发服务器和构建步骤。它的作者也是 Preact 的作者 Jason Miller,所以它对于 Preact 的开发者而言无疑是一个很好的选择。Jason Miller 在 JS Party 的播客中说到 wmr 背后的思考:

“Preact 很小,如果你想要做一个轻量级的项目,那么它确实不错。我们的工具在哪里?我们有一个基于 webpack 的工具,被许多知名的网站所使用,但那是重量级的工具。原型工具在哪里?一段时间以来,我们一直处于打包构建生态系统的边缘,这刺激着人们,尝试就我们可以推进现代代码和发布现代代码的想法上取得共识。”

这告诉我们 wmr 是一个关于编写和发布现代代码,在项目中更轻量的工具。

你可能想知道 wmr 代表着什么?什么都不是!“web 模块运行时”和“web 模块替换”这两个名称都是适用的,但它是一个假的缩写,和 npm 类似。

wmr 采用和 Preact 一样无情的包体积清除方式,所以它十分的小型——体积仅仅只有 2.6MB——并且完全是零 npm 依赖项。尽管如此,它还是打包了许多非常棒的特性,包括热更新和优化的生产构建。

如果我正打算尽可能快的使用 Preact 做一个应用,那么我会使用 wmr。wmr 无需进行配置并且只需花费几秒就能下载下来。wmr 几乎提供了中小型应用所需的一切,例如 TS、优化构建步骤和静态 HTML 渲染。它小型的体积也非常适合快速的试用一个库和演示想法。

如果你不是在使用 Preact,React 或者是 vanilla JS,那么 wmr 可能不是你想找的那个工具。Preact团队还没有为其他框架提供模板。wmr 的文档也没有我们已经看过的其他工具那样详细。所以,如果需要大量的定制化的话,我是不建议它的。

我喜欢使用 wmr 来开发 React 和 Preact 应用。用一个体积相当小的工具开始,但却又给开发者提供了和重量级打包器相似便利的体验非常棒。

wmr
多种前端框架的模板
模块热更新开发服务器
Streaming Imports(按需获取imported package)
预配置的生产构建
自动化的 postcss 和预处理器转换
HTML 转换
支持 Rollup 插件
默认安装的大小2.57MB

特性比较

用例

工具用例
esbuild大型仓库。还没有准备好投入生产使用。
Snowpack不需要打包的小型应用或者是你想要选择自己想要的打包器。对于在服务端渲染的应用中逐步采用JS框架是友好的。
Vite是生产单页用工具Vue CLI / Create-React-App的替代物。对于Vue的使用者是很好的选择。
wmr原型。对于中小型的应用和能够在单页或者服务端渲染的应用来说是友好的。对于Preact的使用者是很好的选择。

设置

esbuildSnowpackVitewmr
多种前端框架的模板
默认安装大小7.34MB16MB17.1MB2.57MB
零配置的生产构建
零配置的热更新开发服务器
支持使用 Process.env 处理 node 的包

开发服务器

esbuildSnowpackVitewmr
模块热更新
CSS 热更新
提前打包 npm 依赖
浏览器展示错误信息
HTML 转换

生产构建

esbuildSnowpackVitewmr
使用测试用例输出的包体积大小177KB184KB165KB164KB
基于 Go 的打包✅当在构建步骤中使用esbuild
预配置的生产构建
异步 chunk 加载
支持 Rollup 插件

其它特性

esbuildSnowpackVitewmr
Streaming imports
服务端渲染
CSS 模块化
自动的 PostCSS 和预处理器转换

结束语

我对刚刚我们看到过的所有构建 JS 应用的工具感到非常的兴奋。不管我们是写了一个小型的项目还是一个大型的生产使用网站,这些工具都能提升生产的效率。它们打开了新的大门,询问在 JS 生态系统中什么是必要的,以及我们是否可以开始丢掉一些遗留模块和浏览器带来的麻烦。这些工具通过提供更精简、更快的开发环境,减少编写的代码和运行在浏览器中的代码之间的抽象,从而降低新开发者的使用门槛。

如果你厌倦了等待依赖下载和构建步骤运行,我建议可以尝试使用新一代的构建工具。