返回博客

Storybook 性能:Vite 与 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 SFCs 等框架特定模块。

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 将预览的构建器从 Webpack 切换到 Vite。

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 开发服务器启动并在浏览器中打开您的 stories。完成工作后,Storybook 会运行生产构建,以便您可以在 CI 中运行测试并发布到 Web。 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 并配合特定的配置来完成此任务。

同样,我们也发现 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 为生产环境打包的 Storybooks 对于最终用户来说加载速度会稍快,并且比使用标准 Webpack 4 或 5 配置生成的 Storybooks 需要更少的带宽。

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 构建器来获得更快的生产构建时间,但您可能会获得更小的生产包,从而加快已发布 Storybooks 的加载时间。

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

Storybook 与 Vite 的未来

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

Storybook 团队已经开始探索对 manager 进行预打包,这样在使用 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,180开发者及更多

我们正在招聘!

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

查看职位

热门文章

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

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

Storybook 6.5

提高效率的新工作流程
loading
Michael Shilman

Figma Storybook 插件

将设计与代码并排放置集成
loading
Dominic Nguyen
加入社区
7,180开发者及更多
缘由为何选择 Storybook组件驱动的 UI
文档指南教程更新日志遥测
社区插件参与其中博客
案例展示探索项目组件词汇表
开源软件
Storybook - Storybook 中文

特别感谢 Netlify CircleCI