2025上半年,最新 AI实践都在这!20+ 应用案例,任听一场议题就值回票价 了解详情
写点什么

在 RSC 中使用 StoreBook

作者:Michael Shilman

  • 2024-07-18
    北京
  • 本文字数:2655 字

    阅读完需:约 9 分钟

大小:974.47K时长:05:32
在RSC中使用StoreBook

将 Storybook 升级到 8.0alpha 版本,可支持 React 服务端组件。

 

在基于 React 的 Web UI 开发中,React服务端组件(RSC)是一种新的编程模式。与传统的 React “客户端”组件不同,它们只在服务器上进行渲染。这为性能和安全方面带来了一些好处,但与当下的各种 React 工具和库相比,其用法有很大的差异。

 

其中受影响最大的领域之一就是基于组件驱动的开发和测试。诸如 Storybook、Testing Library 以及用于组件测试的工具 Playwright 和 Cypress,全都是假设用户组件在浏览器(或 JSDom)中进行渲染。但是对于服务器组件来说,情况就不再是这样了。

 

因此,这就引出了一个问题:该如何独立进行服务器端组件的开发和测试呢?

 

今天,我很高兴地宣布,Storybook 的 Next.js 框架将提供 RSC 支持,算是作为上述问题的一个尝试性的解决方案。由于它是一个纯客户端实现,所以能很好的集成和适配整个 Storybook 插件生态。

 

本文介绍了它的工作原理和用法,并提供了一个简单的教程。

 

服务端来自火星,客户端来自金星

 

RSC 与传统的客户端组件有两个主要区别,如下代码所示:

 

// ApiCard.tsximport { ComponentProps } from 'react';import { Card } from './Card';import { findById } from './db';export async function DbCard({ id }: {id: number}) {  let props;  try {    const contact = await findById(id);    props = { state: 'success', contact };  } catch (e) {    props = { state: 'error' };  }  return <Card {...props} />;}
复制代码

 

  1. 第一个区别是:服务端组件是异步的,而这在客户端上是不支持的。

  2. 第二个区别是:服务端组件可以直接访问 Node 代码,在这个示例中,函数 findById 封装了一个经过验证的数据库连接。

 

为了实现这两点,RSC 在底层做了很多事情。这段代码只能在服务器上运行,并生成一个静态的、类似 JSON 的结构,然后通过流的方式传输给客户端。

 

Storybook 是一个纯客户端应用。它是一个用于生成纯 HTML/CSS/JS 的静态构建,没有任何 Node 的影子!因此,如果要支持 RSC,就需要解决两个问题:要么找出如何在客户端上渲染 RSC 的方法,要么为服务端渲染重构 Storybook。

 

我们首先专注于客户端方法。这是因为,我们希望最大程度地减少对用户的影响,毕竟这些用户已经在当前的架构下编写了数百万个用例和上百个插件。

 

那么,它到底是如何实现的呢?

 

开始支持异步

 

如何支持异步组件是在客户端上渲染 RSC 组件的第一个挑战。幸运的是,在 Next.js 最新依赖的 React 版本中已经(非官方地)支持了这一功能。我们要特别感谢JamesManningRjulRuss,他们为此提供了一个简单的解决方案!

 

import { Suspense } from 'react';export const ClientContact = ({ id }) => (  <Suspense><DbCard id={id} /></Suspense>);
复制代码

 

从 Storybook 8 开始,通过在.storybook/main.js 中开启 experimentalNextRSC 特性,@storybook/nextjs 就会自动将你的 story 封装在 Suspense 中:

 

// .storybook/main.jsexport default {  features: {    experimentalNextRSC: true,  }};
复制代码

 

在 @storybook/nextjs 7.x 版本中,你也可以手动将 RSC story 封装到装饰器中。

 

注意:这个解决方案目前还不能在其他 Storybook React 框架(例如 react-vite、react-webpack5)中使用,因为它们没有像 Next.js 那样使用 canary 版的 React。希望下一个 React 版本能消除这个限制。

 

模拟和加载

解决异步问题只解决了一半的问题。为了完成组件数据的填充,我们的 DbCard 组件是通过调用 Node 代码获取数据。然而,Node 代码在浏览器中无法执行,这就导致了问题!

 

为了解决这个问题,我们建议搭建一个干净的数据访问层。这也是RSC架构师推荐的最佳实践。

 

创建好数据访问层后,你就可以在浏览器中通过模拟来运行它,并精确控制返回的数据,展示不同的用户界面状态(加载中、错误、成功等)。

 

你可以使用模块模拟网络模拟来模拟数据访问层,这两种方式 Storybook 都支持。

 

模块模拟:有一个叫做storybook-addon-module-mock的社区插件,它提供了和 jest.mock(仅适用于 Webpack 项目)类似的模拟功能。当然,也可以使用webpack/vite的别名实现一个简单但功能有限的解决方案。我们计划在 Storybook 的未来版本中提供更便捷的模块模拟功能。

 

网络 API 模拟:为了模拟网络请求,我们推荐使用Mock Service Worker (msw)。当然 Storybook 还支持许多其他网络GraphQL模拟插件。

 

回到上面的例子,下面是一个使用了 storybook-addon-module-mock 的 story:

 

// DbCard.stories.jsimport { StoryObj, Meta } from '@storybook/react';import { createMock } from 'storybook-addon-module-mock';import { DbCard } from './DbCard';import * as db from './db';export default { component: DbCard };export const Success {  args: { id: 1 },  parameters: {    moduleMock: {      mock: () => {        const mock = createMock(db, 'findById');        mock.mockReturnValue(Promise.resolve({          name: 'Beyonce',          img: 'https://blackhistorywall.files.wordpress.com/2010/02/picture-device-independent-bitmap-119.jpg',          tel: '+123 456 789',          email: '[email protected]'        }))        return [mock];      },    },  },}
复制代码

 

完整 Demo:API+模块模拟

要了解完整示例,包括使用模块模拟数据库版本和使用 MSW2 模拟 API 版本,请查看完整StorybookRSC示例GitHub仓库

 


有什么问题吗?

在本文中,我们成功地在 Storybook 中为 RSC 编写了第一个 story,并展示了这一切是在幕后是如何实现的。

 

虽然所有事情都相当的简单明了,但是这种方法还是会有一些限制:

 

  1. 保真度:纯客户端实现与在应用程序中实际运行的服务端流式 RSC 相比依然存在显著的差异。

  2. 便利性:这里的模拟解决方案肯定还有改进的空间。当前的模块模拟解决方案不仅冗长,且与 Storybook 的参数/控件也兼容的不够好。

 

我们计划在后续的迭代中解决这两个问题,这也是为什么我们将此解决方案标记为实验性的原因。

 

现在就在 Storybook 中进行 RSC 开发吧

 

要使用 Storybook 进行 RSC 开发,请将 Storybook 升级到 8.0-alpha 版本:

 

npx storybook@next upgrade --prerelease
复制代码

 

然后,在项目的.storybook/main.ts 文件中将实验性功能开启:

 

// .storybook/main.jsexport default {  features: {    experimentalNextRSC: true,    },  };}
复制代码

 

更多信息,请参阅 @storybook/nextjs 的README文档

 

原文链接:

https://storybook.js.org/blog/storybook-react-server-components/

 

2024-07-18 13:328197

评论

发布
暂无评论
发现更多内容

对数学直观、感性的认知是理解数学、喜爱数学的必经之路,这本书做到了!

图灵教育

高中数学

阿里云张新涛:支持沉浸式体验应用快速落地,阿里云云XR平台发布

阿里云弹性计算

视觉计算 云XR平台 沉浸式体验 GPU实例

【React源码系列】全网最详细的React异常捕获及处理机制

爱切图的木子老师

前端 React react源码 异常捕获

双屏协作更高效,华硕灵耀X 双屏Pro 2022创作体验再升级

科技热闻

毕昇编译器优化:Lazy Code Motion

华为云开发者联盟

云计算 后端 表达式 毕昇编译器

开源一夏 | 基于若依架构的列表详情展示

六月的雨在InfoQ

bootstrap 开源 若依 8月月更

开源一夏 | 对于Angular表达式以及重要指令的研究心得【前端实战Angular框架】

恒山其若陋兮

开源 8月月更

MySQL数据指令

武师叔

8月月更

论文分享:「FED BN」使用LOCAL BATCH NORMALIZATION方法解决Non-iid问题

隐语SecretFlow

密码学和算法 机器学习/深度学习

分贝通SAAS企业大数据体系建设经验分享

阿里云大数据AI技术

大数据

Go-Excelize API源码阅读(五)—— Close()

Regan Yue

Go 开源 源码刨析 8月日更 8月月更

ebook下载 | 《 企业高管IT战略指南——企业为何要落地DevOps》

York

云计算 DevOps 云原生 数字化转型 降本增效

5个 Istio 访问外部服务流量控制最常用的例子,你知道几个?

万猫学社

云原生 istio envoy Istio流量管理

2022 首期线下 Workshop!面向应用开发者们的数据应用体验日来了 | TiDB Workshop Day

TiDB 社区干货传送门

OpenHarmony——内核对象队列之算法详解(下)

OpenHarmony开发者

OpenHarmony

基于设计稿识别的可视化低代码系统实践

Shopee技术团队

前端 设计 低代码

shell之变量详解,让你秒懂!

Albert Edison

Linux centos 运维 shell脚本编程 8月月更

“稚晖君”为2022昇腾AI创新大赛打call 期待广大开发者加入

极客天地

SpringMVC(三、JDBCTemplate)

开源 springmvc 8月月更

winpe工具WEPE微PE工具箱

肖飞码字

windows 操作系统

视频是主动学习吗?

FunTester

分享 6 个 Vue3 开发必备的 VSCode 插件

Geek_z9ygea

vue.js 前端 vscode vuejs

图解VirtualBox安装CentOS 7

万猫学社

Centos 7 virtualbox

10个 Istio 流量管理 最常用的例子,你知道几个?

万猫学社

云原生 istio envoy Istio流量管理

重要的不是成为海贼王,而是像路飞一样去冒险

沃德

十步以内,用小程序快速生成App!

Geek_99967b

小程序

“车家互联”新态势,小程序实现物联网多场景互通

Speedoooo

小程序 智能家居 小程序容器 电动车

为什么数字钱包需要引入小程序生态

Speedoooo

小程序 第三方支付 小程序容器 移动钱包

说了半天跨平台,今儿咱就来跨跨!(完结篇)——Kubernetes上手实践

为自己带盐

Docker WSL2 k8s入门 签约计划第三季 8月月更

开源一夏 | Mysql开启ssl加密协议及Java客户端配置操作指南

六月的雨在InfoQ

MySQL 开源 SSL证书 SSL 连接 8月月更

在RSC中使用StoreBook_大前端_InfoQ精选文章
OSZAR »