写点什么

服务端来自火星,客户端来自金星,RSC 开发新思路

作者:Michael Shilman

  • 2024-01-13
    北京
  • 本文字数:2804 字

    阅读完需:约 9 分钟

大小:1014.13K时长:05:46
服务端来自火星,客户端来自金星,RSC开发新思路

将 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: 'b@beyonce.com'        }))        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文档

 

本文是详细介绍 Storybook 8.0 的第一篇文章,在接下来的几个月里我们将发布更多的内容。请关注我们的社交媒体或订阅Storybook新闻资讯,获取 Storybook 下个版本的全部信息!

 

原文地址:https://storybook.js.org/blog/storybook-react-server-components/

 

相关阅读:


从 Styleguidist 迁移到 Storybook

HTML5 Web Sockets 与代理服务器交互

从新 React 文档看未来 Web 的开发趋势

如何快速构建 React 组件库

2024-01-13 08:007485

评论

发布
暂无评论

MySQL SQL脚本语句加上数据库存在判断

Andy

Git安装和配置教程:Windows/Mac/Linux三平台详细图文教程,带你一次性搞定Git环境

小万哥

git Linux 程序员 后端 C/C++

经典智能合约案例之发红包

timerring

区块链

线程池是如何执行的?任务太多会怎样?

javacn.site

QUIC 协议:特性、应用场景及其对物联网/车联网的影响

EMQ映云科技

车联网 物联网 mqtt QUIC

深度学习进阶篇-国内预训练模型[5]:ERINE、ERNIE 3.0、ERNIE-的设计思路、模型结构、应用场景等详解

汀丶人工智能

人工智能 自然语言处理 深度学习 文心 ERNIE Transformer

七年老程序员的三四月总结:三十岁、准备婚礼、三次分享

拭心

程序人生 总结思考

Typora for Mac:一款极简风格Markdown写作软件

理理

Typora破解 Mac软件 Markdown文本编辑器 Typora Mac下载

软件测试/测试开发丨学习笔记之Web自动化测试

测试人

程序员 软件测试 自动化测试 测试开发 web自动化

用Python做一个翻译器 | Python小知识

AIWeker

Python 人工智能 python小知识

希尔伯特旅馆里,住着AI的某种真相

脑极体

AI 智能涌现

经典智能合约之智能拍卖

timerring

区块链

C语言编程—枚举

芯动大师

Redis和MySQL的爱恨情仇!

Java你猿哥

Java MySQL redis ssm 缓存雪崩

iOS MachineLearning 系列(20)—— 训练生成CoreML模型

珲少

文心一言 VS 讯飞星火 VS chatgpt (24)-- 算法导论4.2 6题

福大大架构师每日一题

福大大 ChatGPT 文心一言 讯飞星火

写给程序员的可逆计算理论辨析

canonical

开源 低代码 Docker 镜像 可逆计算 Nop平台

MySQL 启动apollo-adminservice 报错 Caused by: java.sql.SQLSyntaxErrorException: Unknown column 'serverconf0_.Cluster' in 'field list

Andy

实测 亚马逊AI 编程助手 Amazon CodeWhisperer(全网最全)

攻城先森

人工智能 编程 测试 AWS 亚马逊云科技

太牛了!在GitHub上“千金难求”的SpringBoot趣味实战课免费分享

Java你猿哥

Java spring Spring Boot ssm SpringBoot实战

CSS小技巧使用 font-variation 让文字起飞

南城FE

CSS 设计 前端开发 动画 字体

1行代码合并多个PPT文件,Python自动化办公

程序员晚枫

Python PPT 自动化办公

mac分屏功能怎么用?mac分屏软件推荐 magnet

理理

Magnet中文版 Magnet破解版 mac分屏功能 Magnet Mac下载 苹果窗口管理软件

GPT用于复杂代码生产所需要满足的必要条件

canonical

低代码 GPT GPT-4 可逆计算

2023-05-28:为什么Redis单线程模型效率也能那么高?

福大大架构师每日一题

redis 福大大

StarUML教程:CLI(命令行界面)功能的使用

理理

StarUML教程 CLI(命令行界面) UML软件建模器 StarUML for Mac StarUML Mac破解下载

GitHub星标126K的京东「微服务进阶笔记」首次开源!好评如潮

Java你猿哥

Java 架构 微服务 Spring Cloud ssm

MySQL Idea 启动主程序 无法识别时区

Andy

智能工厂 | 联合汽车电子有限公司汽车驱动科技上海智能工厂

工赋开发者社区

大模型全情投入,低代码也越来越清晰

引迈信息

低代码 大模型 JNPF

软件测试/测试开发丨学习笔记之用户端Web自动化测试

测试人

程序员 软件测试 自动化测试 测试开发 web自动化

服务端来自火星,客户端来自金星,RSC开发新思路_跨端开发_InfoQ精选文章