返回博客

Storybook 性能:Vite vs Webpack

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

loading
Ian VanSchooten
@ianvanschooten
最后更新

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

Storybook 在首次启动或重建已更改文件时的性能,很大程度上取决于它如何捆绑故事和组件。优化构建过程为 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(侧边栏、面板、按钮等)和预览(您的故事和文档页面)。在 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 个故事,混合使用了 CSFMDX 格式。Carbon 使用 Webpack 5,但没有懒加载编译或代码拆分功能。它的配置与 Webpack 没有紧密耦合,从而可以相对直接地迁移到 Vite 构建器。

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

方法

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

我对我的 2019 Intel Macbook Pro 上的每个时间取了五个样本的平均值。我比较了五种不同的 Storybook 构建器配置的结果

  • Webpack 4
  • Webpack 5
  • Webpack 5 LC/CS(启用懒加载编译和代码拆分)
  • Vite
  • Vite CS(启用代码拆分)

结果

Storybook 可以通过两种不同的方式构建您的应用程序。 当您在开发期间使用它时,您必须等待 storybook 开发服务器启动并在浏览器中打开您的故事。完成时,Storybook 运行生产构建,以便您可以在 CI 中运行测试并发布到网络。 Storybook 还在您每次保存时重新构建您的故事,因此我们还将查看这需要多长时间。

开发(冷启动)

我们将要检查的第一个场景是开发服务器的冷启动。这是您第一次运行 start-storybook 到故事加载到浏览器之间等待的时间。

Carbon 项目使用其默认配置(Webpack 5,未启用代码拆分或懒加载编译)启动开发服务器并在浏览器中渲染故事需要 61 秒,与 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 拔得头筹,在第一个故事加载之前需要 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,您需要使用 build-storybook 将其构建为静态 Web 应用程序。与本地开发不同,生产构建不需要 HMR。因此,Vite 不会提供单个模块,而是将所有内容捆绑在一起,类似于 Webpack。在底层,它使用 Rollup 和 opinionated 配置来完成此任务。

在这里我们也发现,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 构建也使用代码拆分,这解释了上面看到的较小的请求大小。另请记住,虽然代码拆分允许第一页加载更快,但导航到其他故事可能需要稍长的时间,因为每次都需要请求和下载更多的 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 相当。

Vite 支持的 Storybook 的未来

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 邮件列表

获取最新新闻、更新和发布

6,730开发者人数不断增加

我们正在招聘!

加入 Storybook 和 Chromatic 背后的团队。构建被数十万开发者用于生产环境的工具。远程优先。

查看职位

热门文章

使用 Storybook 自动化可访问性测试

使用 Accessibility 插件在开发期间运行检查,并使用测试运行器捕获回归
loading
Varun Vachhar

Storybook 6.5

让您更高效的新工作流程
loading
Michael Shilman

Storybook Figma 插件

并排集成设计和代码
loading
Dominic Nguyen
加入社区
6,730开发者人数不断增加
为什么为什么选择 Storybook组件驱动的 UI
文档指南教程更新日志遥测
社区插件参与其中博客
展示探索项目组件词汇表
开源软件
Storybook - Storybook 中文

特别感谢 Netlify CircleCI