
开始使用 Storybook 和 Next.js
用四个简单步骤将 Storybook 集成到 Next.js 中

2023年更新:Storybook 与 NextJS 实现了零配置集成。在此处 了解如何使用它。
Next.js 是一个用于构建高性能 React 应用程序的优秀框架。但随着其功能的日益强大——例如 next/image ——与 Storybook 等文档和测试环境的集成也变得更加困难。
我深入研究了如何使 Storybook 成为 Next.js 页面的最佳 组件驱动 UI 环境。本文将向您展示如何在四个简单步骤中完成此操作。
- 📦 使用 Webpack 5 初始化新的 Storybook
- 📑 为 Next.js 页面创建 stories
- 🌎 在 preview.js 中导入共享的全局样式
- ⬇️ 为 Stories 中的 Next Image 进行去优化
如果您更喜欢视频,请跳转到文末。我们在一个 27 分钟的 YouTube 视频中涵盖了所有这些步骤(以及更多内容)!
开始一个 Next.js 应用
在开始之前,我们需要一个 Next.js 应用。本教程使用 nextjs.org 上的优秀 入门指南。

我建议先在新应用中跟随操作,然后再在现有应用中重复这些步骤。 完整的源代码在 Github 上,已更新为 Next.js 12。
使用 Webpack 5 初始化新的 Storybook
Storybook 有一个初始化器可以为我们完成繁重的工作:npx sb init。此脚本会检测您的项目类型并适应它。但我们也可以提供一些提示。
Next.js v11 及更高版本使用 Webpack 5。我们也可以在 Storybook 中使用 Webpack 5 来获得更好的集成和性能。为此,我们使用 builder 选项并运行此命令:
npx sb init --builder webpack5了解更多关于 Storybook 的 Webpack 5 构建器的好处。
为完整的 Next.js 页面创建 stories
Next.js 和 Storybook 拥有极其兼容的组件模型。Next.js 使用组件来表示页面,Storybook 使用组件进行文档和测试。这使得 Storybook 成为 Next.js 的绝佳组件驱动开发环境!
让我们为我们的 Next.js 主页创建一个 story。
- 创建一个新文件
/stories/pages/home.stories.jsx - 导入
/pages/index.js - 导出一个默认的 story 对象,其中包含
title和component属性 - 为
Home导出 story
// /stories/pages/home.stories.jsx
import Home from "../../pages/index";
export default {
title: "Pages/Home",
component: Home,
};
export const HomePage = () => <Home />
现在我们的 Home 页面已在 Storybook 中。但它目前还不好看。我们需要导入全局样式。

在 preview.js 中导入共享的全局样式表
大多数应用程序都有用于全局重置或字体样式的样式表,这些样式表被全局共享。我们的 Next.js 教程应用将全局样式保存在 /styles/globals.css 中。
我们可以将全局样式表导入到我们的 home.stories.jsx story 文件中。但这将需要在 story 文件中进行大量重复操作——这是一个非常容易出错的过程。最好为所有 stories 导入全局样式表。
Storybook 在 .storybook/preview.js 中保存共享的 story 配置。此文件控制所有 stories 的渲染方式。可以使用模块导入来导入样式表。
// .storybook/preview.js
import "../styles/globals.css";

我们做到了!除了一个损坏的图片,我们的 story 看起来就像从 Next.js 提供的首页一样。
有关处理 Storybook 中样式的更多方法,请参阅我们的 样式和 CSS 指南。
为 Stories 中的 Next.js Image 进行去优化
Next.js 和 Storybook 集成中最具挑战性的部分是处理图像。

Next.js v10 及更高版本包含 Next.js Image 组件。用他们的话来说,它是“HTML <img> 元素的扩展,为现代 Web 而演进。” 使用它可优化文件大小、视觉稳定性和加载时间。这是 UI 工程的一个奇迹。
由于 Storybook 在 Next.js 框架集成之外独立运行这些组件,我们需要从两个重要方面进行配置:
- 在 Storybook 中服务 public 目录
- 在所有 stories 中为 Next.js Image 组件添加
unoptimized属性
1. 在 Storybook 中服务 public 目录
sb init 脚本在我们的 package.json 中创建了两个 Storybook 脚本。更新它们以服务 public 目录(Next.js 图像所在的位置)。我们使用的 CLI 选项是 -s 或 --static-dir。
// package.json
"scripts": {
- "storybook": "start-storybook -p 6006",
- "build-storybook": "build-storybook"
+ "storybook": "start-storybook -p 6006 -s ./public",
+ "build-storybook": "build-storybook -s public"
}
在我们的 CLI 选项文档 中查找更多 CLI 选项。并了解更多关于 通过 Storybook 服务静态文件。
2. 在 Storybook 中为 Next.js Images 使用 unoptimized 属性
在任何使用 Next.js Image 组件的地方,图像都从 /_next 前缀的路径提供。我们希望利用 Next Image 的属性 API 和属性,但我们不想要求 Next.js 开发服务器正在运行。我们可以使用 unoptimized 属性来做到这一点。但如何在 Storybook 中做到这一点,而不是在 Next.js 中呢?🤔
通过一点模块技巧,我们可以仅在 stories 中去优化 Next.js Image。
// .storybook/preview.js
import * as NextImage from "next/image";
const OriginalNextImage = NextImage.default;
Object.defineProperty(NextImage, "default", {
configurable: true,
value: (props) => <OriginalNextImage {...props} unoptimized />,
});
这段配置代码会修改 Storybook 如何评估 next/image 模块。在任何使用 Next.js Image 默认导出的地方,都会应用 unoptimized 属性。
重新启动服务器并查看底部的 Vercel SVG。我们又回来了!
有关此技术的更多信息,请阅读如何在 Storybook 中使用 Next.js Image 组件——这是 Jonas Schumacher 发表的一篇精彩文章。


下一步是什么?
您已经在此 Next.js 和 Storybook 集成方面做得非常出色。但我们还有很多事情可以做!
如果您还想了解更多,请查看我的 YouTube 教程。我将此集成进一步扩展,并使用 Mock Service Worker 来处理 getServerSideProps 和 getStaticProps。
您有什么 Next.js🤝Storybook 技巧?
我们希望听到您的声音!
您有什么关于使 Next.js 和 Storybook 成为超级开发环境的智慧可以分享?请在此评论或加入 Storybook Discord 服务器!我们迫不及待地想见到您 🤩
Next.js 12 已发布! @chantastic 分享了四个快速技巧,帮助您充分利用 Next.js 和 Storybook!
— Storybook (@storybookjs) 2021年11月10日
📦 使用 Webpack 5
📑 为 Next.js 页面编写 stories
🌎 在 preview.js 中导入共享的全局样式
⬇️ 集成 next/imagehttps://#/By5EfB4XnI pic.twitter.com/jED2qN0crP