返回博客

Storybook 性能:Vite vs Webpack

我们对这两个构建器进行了基准测试,以查看哪个更快。

loading
Ian VanSchooten
@ianvanschooten
最后更新

Storybook 是行业标准的 UI 组件工作室。全球成千上万的应用程序和设计系统团队的大部分时间都在 Storybook 中工作——构建、记录和测试他们的 UI 组件。因此,Storybook 需要尽可能快地运行,以免拖慢他们的工作流程。

Storybook 在首次启动或重新构建已更改文件时的性能很大程度上取决于它如何打包 stories 和组件。优化构建过程为 Storybook 提供了许多性能提升的机会。Webpack 和 Vite 构建器的改进是这项更大、持续进行的优化工作的一部分。

本文将探讨一些可以帮助您获得最快开发体验的选项。我们将考察升级到 Webpack 5 的影响,启用代码分割或延迟编译等功能,最后切换到 Vite 构建器。Storybook 致力于为 Vite 项目提供一流的支持,而获取我们性能的基线是进一步优化的第一步。

Storybook 构建器

Storybook 由 构建器(如 Webpack)提供支持,这些构建器会处理和打包您的代码——Javascript、TypeScript、CSS、MDX,甚至包括 Vue 或 Svelte SFC 等特定于框架的模块。

Diagram of parts of your code (js, css, mdx, etc) being joined by Storybook into the storybook app, with the manager UI of the sidebar, toolbar, and addons pane, and the preview iframe of the stories themselves.

目前,Webpack 是 Storybook 的默认构建器。Storybook 使用 Webpack 来编译自己的 UI(侧边栏、面板、按钮等)和预览(您的 stories 和文档页面)。从 Storybook 6.4 及以上版本开始,可以切换到 @storybook/builder-vite 来使用 Vite 而不是 Webpack 来构建预览。

Storybook Vite 构建器

Vite 是一个下一代构建工具,旨在提供更快、更轻巧的开发体验。它不将您的整个项目打包成一个或多个块,而是在开发过程中将单个 ES 模块提供给浏览器。这使得它几乎可以瞬间启动。然后,当您更新代码时,热模块替换 (HMR) 只需替换一个小文件,而不是重新打包整个应用程序,从而使重建速度极快。

当使用 Storybook Vite 构建器时,您将能够使用与您的应用程序相同的 Vite 插件和配置,并继续利用 Storybook 插件生态系统的优势。

那么,既然 Vite 承诺了如此出色的性能,Webpack 是不是就被淘汰了?嗯,等等,Storybook 团队一直在努力提高 Webpack 的性能。他们引入了 延迟编译等功能来加快开发性能,以及 按需架构 来利用代码分割来减少初始加载时间。

让我们来看看这些更改是否足以在一个实际的 Storybook 项目中匹配 Vite 的性能。

使用 IBM Carbon Design System 对 Storybook 性能进行基准测试

为了比较这两种构建器的性能,我选择对 IBM 的 Carbon Design System 运行基准测试。Carbon 的 Storybook 相对较大,拥有 100 多个 React 组件和 250 个 stories,使用了 CSFMDX 格式的混合。Carbon 使用 Webpack 5,但未使用延迟编译或代码分割功能。它的配置并未与 Webpack 紧密耦合,这使得迁移到 Vite 构建器相对直接。

这只是一个示例项目,这些结果可能与您自己项目中的结果不同。性能是一个复杂的主题,会受到多种因素的影响,但 Carbon 项目中的结果说明了 Storybook 构建器选项之间的一些有趣差异。

方法

在深入研究结果之前,让我解释一下我是如何运行这些基准测试的。我使用了 @storybook/bench 来全面了解构建器之间的性能差异。它测量了开发服务器启动和在浏览器中渲染 story 的总时间、创建生产构建所需的时间,以及浏览器渲染已发布的 Storybook 的第一个 story 所需的时间。我还计算了从编辑文件到 story 在浏览器中重新渲染的总体时间(使用 HMR)。

我在我的 2019 年 Intel Macbook Pro 上对这些时间进行了五次采样的平均值。我比较了五个不同 Storybook 构建器配置的结果:

  • Webpack 4
  • Webpack 5
  • Webpack 5 LC/CS(启用了延迟编译和代码分割)
  • Vite
  • Vite CS(启用了代码分割)

结果

Storybook 可以有两种不同的方式来构建您的应用程序。当您在开发过程中进行开发时,您需要等待 storybook 开发服务器启动并在浏览器中打开您的 stories。完成后,Storybook 会运行一个生产构建,以便您可以在 CI 中 运行测试 并发布到网上。Storybook 在您处理它时,每次保存都会重新构建您的 story,所以我们也会看看这需要多长时间。

开发(冷启动)

我们首先要检查的是开发服务器的冷启动。这是从第一次运行 start-storybook 到 story 在浏览器中加载之间等待的时间。

Carbon 项目的默认配置(Webpack 5,未启用代码分割或延迟编译)需要 61 秒才能启动开发服务器并在浏览器中渲染 story,这大约与 Webpack 4 所需的时间相同。但是,启用延迟编译可以将该时间减半至 30 秒。

Bar chart of Time to First Story (cold) results. Webpack 4: 59.5s, Webpack 5: 60.9s, Webpack 5 (lazy compilation & code-splitting): 30.3s, Vite: 103.8s, Vite (code-splitting): 36.7s.

Vite 以闪电般的速度著称,但令人惊讶的是,它在第一次页面加载时速度较慢。发生了什么?请记住,Vite 将每个模块未经打包地发送到浏览器,因此尽管开发服务器启动很快,但浏览器需要更多时间来下载和处理所有这些请求。

作为对比,Webpack 向浏览器发送 16 到 33 个资源,而 Vite 则发送多达 1,060 个资源(如果未启用代码分割)。

启用代码分割(storyStoreV7)可将该数字大幅减少到 250,我们看到速度有所提高,尽管启动速度仍然略慢于启用了延迟编译的 Webpack 5。

带缓存的开发(温启动)

第一次运行后,Storybook 会缓存一些构建产物,因此后续启动速度更快。这里的构建时间确实比以前更快,并且相同的模式也适用。Webpack 5 启用延迟编译后,首次加载 story 只需 11 秒,紧随其后的是 Vite 启用代码分割,需要 15 秒。基准的 Webpack 4 和 Webpack 5 配置几乎需要半分钟。

Bar chart of Time to First Story (warm) results. Webpack 4: 29.6s, Webpack 5: 29.3s, Webpack 5 with lazy compilation & code-splitting: 10.8s, Vite: 48.1s, Vite with code-splitting: 14.7s.

生产构建时间

要在线 发布 您的 Storybook,您需要将其构建为静态 Web 应用程序,使用 build-storybook。与本地开发不同,生产构建不需要 HMR。因此,Vite 不会服务单个模块,而是像 Webpack 一样将所有内容打包在一起。在这方面,它使用 Rollup 和一组有针对性的配置来完成此任务。

在这里,我们也发现 Vite 打包资源比 Webpack 需要更长的时间。

Bar chart of production build results. Webpack 4: 71.3s, Webpack 5: 77.5s, Webpack 5 with lazy compilation & code-splitting: 75.4s, Vite: 96.8s, Vite with code-splitting: 81.9s.

生产加载大小和时间

Vite 使用 Rollup 来执行比 Webpack 更积极的 死代码消除(tree shaking),这就是为什么它需要更长的时间来创建生产构建。然而,其权衡是它会生成更小的捆绑包,如下面的图表所示。

通常,这意味着 Vite 打包的 Storybook 在生产环境中将比使用标准 Webpack 4 或 5 配置生成的 Storybook 加载速度稍快,并且需要更少的带宽。

Bar chart of Request size results. Webpack 4: 12.4MB, Webpack 5: 11.6MB, Webpack 5 with lazy compilation & code-splitting: 7.3MB, Vite: 9.4MB, Vite with code-splitting: 5.7MB.

请注意,延迟编译仅适用于开发模式,但 Webpack 5 LC/CS 构建也使用代码分割,这解释了上面看到的更小的请求大小。同时也要记住,虽然代码分割可以使第一个页面加载得更快,但导航到其他 stories 可能需要更长的时间,因为每次都会请求和下载更多的 JavaScript。

重建时间(热模块重载)

到目前为止,Vite 的表现并不那么令人满意。与启用延迟编译的 Webpack 5 相比,Vite 的开发启动时间稍慢,生产构建时间也略长,即使启用了代码分割。

但开发人员喜欢 Vite 的一个主要原因是,从保存文件到在浏览器中看到更改之间的近乎即时的反馈循环。这也就是它在开发过程中提供未打包文件服务的原因。毫不奇怪,这正是 Vite 的闪光点。React 组件的更改只需半秒即可出现在浏览器中,而 Webpack 则需要长达三秒半。

Bar chart of Hot Module Reloading (HMR) results. Webpack 4: 2.26s, Webpack 5: 3.67s, Webpack 5 with lazy compilation & code-splitting: 1.01s, Vite: 0.53s, Vite with code-splitting: 0.50s.

Webpack 的延迟编译将刷新时间缩短到仅一秒,但这仍然是 Vite 的两倍。这些数字可能看起来很小,但它们加起来会产生很大的不同。使用 Vite 时,您的更改似乎瞬时发生,这使得您在构建组件时能够保持思路流畅并快速迭代。

要点

Vite 具有闪电般的重建速度,但您需要启用代码分割功能才能获得全部好处,并避免大型项目的页面加载速度过慢。

// .storybook/main.js
 
module.exports = {
 stories: [],
 addons: ['@storybook/addon-essentials'],
 features: {
   storyStoreV7: true,
 },
 core: { builder: "@storybook/builder-vite" },
};

不要期望通过切换到 Vite 构建器来获得更快的生产构建时间,但您可能会获得更小的生产捆绑包,从而加快已发布 Storybook 的加载速度。

如果您的应用程序严重依赖 Webpack,升级到 Webpack 5 并启用代码分割和延迟编译将是一个快速的改进。在大多数情况下,您可以期望启动和重建时间与 Vite 相当。

Storybook 与 Vite 的未来

Storybook 对 Vite 的支持正在不断改进。Vite 构建器最初是一个社区项目,由 Ian VanSchooten(我)、Josh WoodingEirik Sletteberg 维护。最近,它被移到了 @storybook 组织下,以改进 Storybook 中对 Vite 的支持。

Storybook 团队已经开始探索预打包管理器,这样您在使用 Vite 构建器时就不再需要安装 Webpack 了。未来,使用 HTTP/3 应该有助于降低 Vite 一次性将大量模块发送到浏览器的成本,我们将寻找其他提高性能的方法。在收集这篇博文的数据时,我们已经发现了一个改进,可以将示例构建时间加快 50% 以上。

我鼓励您尝试 Storybook 的 6.5 beta 版本,并尝试构建器功能以使您的 Storybook 更快。每个项目都不同,在一个项目中效果好的东西在另一个项目中可能不适用。要尝试 Vite,请使用 npm create vitenpx sb@next init 命令在新项目中设置 Storybook。对于使用 Webpack 的现有项目,请查看 配置指南 以利用 Webpack 5 的性能改进。或者使用 安装说明迁移到 Vite。

我们非常希望您能参与到这个项目中来。请访问 Storybook Discord 的 #vite 频道 来报告问题或分享改进建议。我也很乐意回答有关此基准测试项目的任何问题。如果这些结果让您感到惊讶,或者它们与您自己的经验一致,请在 Twitter 上告诉我们。

加入 Storybook 邮件列表

获取最新消息、更新和发布信息

7,468开发者及更多

我们正在招聘!

加入 Storybook 和 Chromatic 团队。构建被数十万开发人员在生产中使用的工具。远程优先。

查看职位

热门帖子

使用 Storybook 自动进行可访问性测试

在开发过程中使用“Accessibility”插件运行检查,并使用测试运行程序捕获回归。
loading
Varun Vachhar

Storybook 6.5

新的工作流程,让您更具生产力
loading
Michael Shilman

用于 Storybook 的 Figma 插件

并排集成设计和代码
loading
Dominic Nguyen
加入社区
7,468开发者及更多
原因为什么选择 Storybook组件驱动的 UI
文档指南教程更新日志遥测
社区插件参与进来博客
展示探索项目组件词汇表
开源软件
Storybook - Storybook 中文

特别感谢 Netlify CircleCI