返回博客

开始使用 Storybook 和 Next.js

通过四个简单步骤集成 Storybook 与 Next.js

loading
Michael Chan
@chantastic
最后更新

2023 年更新:Storybook 创建了一个零配置的 NextJS 集成。请在此处了解如何使用它。

Next.js 是一个构建 React 高性能应用的绝佳框架。但随着它的功能越来越先进,例如引入了 next/image 等特性,将其与 Storybook 等文档和测试环境集成变得更加困难。

我深入研究了如何将 Storybook 打造成 Next.js 页面的最佳组件驱动 UI 环境。本文将向您展示如何通过四个简单的步骤实现同样的目标

  • 📦 使用 Webpack 5 初始化一个新的 Storybook
  • 📑 为 Next.js 页面创建故事
  • 🌎 在 preview.js 中导入共享的全局样式
  • ⬇️ 在故事中使用时取消优化 Next Image

如果您更喜欢视频,请跳转到文章末尾。我们在一个 27 分钟的 YouTube 视频代码演示中涵盖了所有这些步骤(以及更多内容)!

从一个 Next.js 应用开始

在我们开始之前,我们需要一个 Next.js 应用。本教程使用了 nextjs.org 上精彩的入门指南

Screenshot of a browser showing a new Next.js app running at localhost:3000
在浏览器中运行的全新的 Next.js 应用

我建议您在一个新应用中跟着操作,然后在现有应用中重复这些步骤。这里是 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 页面创建故事

Next.js 和 Storybook 具有高度兼容的组件模型。Next.js 使用组件来构建页面,而 Storybook 使用组件来构建文档和测试。这使得 Storybook 成为了 Next.js 的绝佳组件驱动开发环境!

让我们为我们的 Next.js 主页创建一个故事。

  • 创建一个新文件 /stories/pages/home.stories.jsx
  • 导入 /pages/index.js
  • 导出一个默认故事对象,带有 titlecomponent 属性
  • 导出一个名为 Home 的故事
// /stories/pages/home.stories.jsx

import Home from "../../pages/index";

export default {
  title: "Pages/Home",
  component: Home,
};

export const HomePage = () => <Home />

现在我们的主页已经在 Storybook 中了。但它看起来还不太完整。我们需要导入全局样式。

在 preview.js 中导入共享的全局样式表

大多数应用都有用于全局重置或字体样式的共享全局样式表。我们的 Next.js 教程应用将全局样式保存在 /styles/globals.css 中。

我们可以将全局样式表导入到 home.stories.jsx 故事文件中。但这样做需要在故事文件中进行大量重复——这是一个非常容易出错的过程。最好一次性为所有故事导入全局样式表。

Storybook 将共享的故事配置保存在 .storybook/preview.js 中。这个文件控制着所有故事的渲染方式。可以通过模块导入来导入样式表

// .storybook/preview.js
import "../styles/globals.css";

我们做到了!除了一个图片破损外,我们的故事看起来就像 Next.js 提供的首页一样。

有关 Storybook 中处理样式的更多方法,请查阅我们的样式和 CSS 指南。

在故事中取消优化 Next.js Image

Next.js 和 Storybook 集成中最具挑战性的部分是处理图片。

Screenshot showing Storybook rendering Next.js app homepage with devtools open. The image is a broken link because the path is not one Storybook supports.
必须配置 Storybook 以提供 /public 目录中的 next/images

Next.js v10 及更高版本包含Next.js Image 组件。用他们的话说,它是“HTML <img> 元素的扩展,为现代 Web 进行了演进。”利用它可以优化文件大小、视觉稳定性和加载时间。它是 UI 工程学的奇迹。

由于 Storybook 在与 Next.js 框架集成隔离的环境中运行这些组件,我们需要通过两种重要方式对其进行配置

  1. 在 Storybook 中提供 Next.js 的 public 目录
  2. 在所有故事中向 Next.js Image 组件添加 unoptimized prop

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 Image 使用 unoptimized prop

凡是使用 Next.js Image 组件的地方,图片都从以 /_next 为前缀的路径提供服务。我们希望利用 Next Image 的 prop API 和属性,但我们不希望要求 Next.js 开发服务器必须运行。通过 unoptimized prop 就可以做到这一点。但是如何在 Storybook 中做到这一点,而在 Next.js 中却不行呢 🤔

通过一些模块技巧,我们可以在故事中仅对 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 prop。

重启服务器,看看底部的 Vercel SVG。我们又回来了!

有关此技术的更多信息,请阅读 Jonas Schumacher 的一篇精彩文章:《如何在 Storybook 中使用 Next.js Image 组件》。

接下来是什么?

您在 Next.js 和 Storybook 集成方面已经做得非常出色了。但我们还有很多事情可以做!

如果您渴望更多内容,请观看我的 YouTube 教程。我通过Mock Service Worker 进一步深化了这种集成,以便与 getServerSidePropsgetStaticProps 一起使用。

您有什么 Next.js🤝Storybook 技巧吗?

我们期待听到您的声音!

关于如何将 Next.js 和 Storybook 打造成超级开发环境,您有什么可以分享的智慧吗?请在此处评论或加入 Storybook Discord 服务器!我们迫不及待地想见到您 🤩

加入 Storybook 邮件列表

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

7,180开发者正在使用

我们正在招聘!

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

查看职位

热门文章

使用 Storybook 文档化您的设计系统的 4 种方法

如何将 UI 组件、规范和使用指南一起展示
loading
Varun Vachhar

Storybook + Netlify CMS

将您的内容带到 Storybook
loading
Varun Vachhar

交互式故事 (beta)

使用播放函数模拟用户行为
loading
Varun Vachhar
加入社区
7,180开发者正在使用
为什么为什么选择 Storybook组件驱动的 UI
文档指南教程更新日志遥测数据
社区插件参与进来博客
案例展示探索项目组件术语表
开源软件
Storybook - Storybook 中文

特别感谢 Netlify CircleCI