测试 React 服务器组件
了解如何在 Expo 中为 React 服务器组件编写单元测试。
重要 本指南涉及仍在开发中的实验性功能 React 服务器组件。
React 服务器组件(RSC)是 React 的一项新功能,允许你构建在服务器上渲染并可以在客户端进行水合的组件。本指南提供了有关如何在项目中为 RSC 编写单元测试的详细信息。
🌐 React Server Components (RSC) is a new feature in React that allows you to build components that render on the server and can be hydrated on the client. This guide provides details on how to write unit tests for RSC in your project.
Jest 测试
🌐 Jest testing
React 服务器组件运行在 Node.js 上。这意味着单独使用 Jest 就可以较为接近地模拟服务器端渲染环境,这与需要通过 Jest 预设在 Node.js 和网页浏览器之间进行通信的客户端测试不同。
🌐 React Server Components run on Node.js. This means Jest on its own can closely emulate the server-side rendering environment, in contrast with client-based tests that require a Jest preset to communicate between Node.js and a web browser.
设置
🌐 Setup
虽然标准的服务器渲染仅限于网页,但 Expo 的通用 RSC 为每个平台打包了自定义的服务器渲染器。这意味着支持平台特定的文件扩展名。例如,在为 iOS 应用编写服务器组件时,会解析像 *.ios.js 和 *.native.ts 这样的平台特定扩展名。
🌐 While standard server rendering is web-only, Expo's universal RSC bundles custom server renderers for each platform. This means platform-specific file extensions are supported. For example, when writing Server Components for an iOS app, platform-specific extensions such as *.ios.js and *.native.ts will be resolved.
jest-expo 提供了几种不同的预设,用于测试服务器组件:
| 运行器 | 描述 |
|---|---|
jest-expo/rsc/android | 仅用于 Android 的 RSC 运行器。使用 *.android.js、*.native.js 和 *.js 文件。 |
jest-expo/rsc/ios | 仅用于 iOS 的 RSC 运行器。使用 *.ios.js、*.native.js 和 *.js 文件。 |
jest-expo/rsc/web | 仅用于 Web 的 RSC 运行器。使用 *.web.js 和 *.js 文件。 |
jest-expo/rsc | 一个多平台运行器,结合了上述运行器。 |
要为 RSC 配置 Jest,请在项目根目录创建一个 jest-rsc.config.js 文件:
🌐 To configure Jest for RSC, create a jest-rsc.config.js file in your project's root:
module.exports = require('jest-expo/rsc/jest-preset');
然后,你可以在你的 package.json 中添加一个脚本,例如 test:rsc:
🌐 Then, you can add a script such as test:rsc to your package.json:
{ "scripts": { "test:rsc": "jest --config jest-rsc.config.js" } }
编写测试
🌐 Writing tests
测试应写在 rsc_tests 目录中,以防止 Jest 在服务器上运行你的客户端测试。
🌐 Tests should be written in a __rsc_tests__ directory to prevent Jest from running your client tests on the server.
/// <reference types="jest-expo/rsc/expect" /> import { LinearGradient } from 'expo-linear-gradient'; it(`renders to RSC`, async () => { const jsx = ( <LinearGradient colors={['cyan', '#ff00ff', 'rgba(0,0,0,0)', 'rgba(0,255,255,0.5)']} testID="gradient" /> ); await expect(jsx).toMatchFlight(`1:I["src/LinearGradient.tsx",[],"LinearGradient"] 0:["$","$L1",null,{"colors":["cyan","#ff00ff","rgba(0,0,0,0)","rgba(0,255,255,0.5)"],"testID":"gradient"},null]`); });
你在测试文件中导入的任何代码都将在服务器环境中运行。你可以导入仅适用于服务器的模块,例如 react-server 和 server-only。这对于确定一个库是否与 RSC 兼容非常有用。
🌐 Any code you import in your test files will run in the server environment. You can import server-only modules like react-server and server-only. This is useful for determining if a library is compatible with RSC.
自定义期望匹配器
🌐 Custom expect matchers
jest-expo 为 RSC 在 Jest 的 expect 中添加了几个自定义匹配器:
toMatchFlight:使用 Expo CLI 中渲染的伪实现渲染 JSX 元素并与航班字符串进行比较。toMatchFlightSnapshot:与toMatchFlight相同,但将飞行字符串保存到快照文件中。
在幕后,这些方法处理渲染 RSC 所需的框架操作的一部分。组件的渲染流会被缓冲成字符串,然后一次性进行比较。你也可以选择手动流式传输,以观察渲染进度。
🌐 Behind the scenes, these methods handle a part of the framework operation needed to render RSC. The component's render stream is buffered to a string and compared all at once. You can alternatively stream it manually to observe the rendering progress.
如果组件无法渲染,匹配器将抛出一个错误以使测试失败。实际上,服务器渲染器会生成一行 E:,该行将发送到客户端本地抛出给用户。
🌐 If a component fails to render, the matcher will throw an error to fail the test. In practice, the server renderer will generate an E: line, which will sent to the client to be thrown locally for the user.
运行测试
🌐 Running tests
你可以使用 test:rsc 脚本运行你的测试:
🌐 You can run your tests with the test:rsc script:
- yarn test:rsc --watch如果你正在使用多运行器,你可以使用 --selectProjects 标志选择特定项目。以下示例仅运行 Web 平台:
🌐 If you're using the multi-runner, you can select a specific project using the --selectProjects flag. The following example only runs the web platform:
- yarn test:rsc --watch --selectProjects rsc/web环境
🌐 Environments
在 RSC 打包环境中,你可以导入以下文件:
🌐 In an RSC bundling environment, you can import files like
提示
🌐 Tips
使用 server-only 和 client-only 模块来断言某个模块不应在客户端或服务器上导入:
🌐 Use the server-only and client-only modules to assert that a module should not be imported on the client or server:
import 'server-only';
RSC 默认支持包导出。你可以使用 react-server 条件来更改从模块导入的文件:
🌐 RSC supports package exports by default. You can use the react-server condition to change what file is imported from a module:
{ "exports": { ".": { "react-server": "./index.react-server.js", "default": "./index.js" } } }
在为 RSC 打包时,所有模块都会以 React 服务器模式打包,你可以使用 "use client" 指令选择退出。当发现 "use client" 时,该模块会变成对客户端模块的异步引用。
🌐 When bundling for RSC, all modules are bundled in React Server mode and you can opt out with the "use client" directive. When "use client" is found, the module becomes an async reference to the client module.
"use server"并不是"use client"的相反。它用于定义一个 React 服务器函数文件。