返回部落格

React 伺服器元件的 Storybook

透過升級至 Storybook 8.0 alpha 版本,在 Storybook 中使用 RSC

loading
Michael Shilman
@mshilman
上次更新

React 伺服器元件 (RSC) 是基於 React 的 Web UI 的全新程式設計模型。與傳統的 React「客戶端」元件相比,它們在伺服器上渲染。這帶來了各種效能和安全性優勢,但這也與我們今天使用的 React 工具和函式庫大相逕庭。

受影響最大的領域之一是元件驅動開發和測試。諸如 Storybook、Testing Library 和 Playwright/Cypress 元件測試之類的工具都假設使用者的元件正在瀏覽器(或 JSDom)中渲染。但是對於伺服器元件,情況不再如此。

這產生了一個問題:對於伺服器,隔離的元件開發和測試意味著什麼?

今天,我很高興發布 Storybook 的 Next.js 框架中的 RSC 支援,作為對這個問題的實驗性解答。它是一個純客戶端實作,使其與 Storybook 擴充套件和整合的整個生態系統相容。

繼續閱讀以了解它是如何運作、如何使用它,以及您今天如何試用它!

伺服器來自火星,客戶端來自金星

RSC 與傳統客戶端元件有兩個主要區別,這兩個區別都存在於以下範例中

// ApiCard.tsx

import { 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. 第一個區別是我們的元件是 async,客戶端不支援此功能。
  2. 第二個區別是我們的元件可以直接存取 Node 程式碼,在本例中是包裝已驗證資料庫連線的 findById 函數。

RSC 在底層做了很多工作來實作這兩個區別。此程式碼僅在伺服器上執行,並且產生靜態 JSON 類型的結構,該結構被串流傳輸到客戶端。

Storybook 是一個純客戶端應用程式。它產生純 HTML/CSS/JS 的靜態建置,沒有任何 Node!因此,支援 RSC 需要弄清楚如何在客戶端上渲染 RSC,或者為伺服器重新架構 Storybook。

我們首先專注於客戶端方法。我們希望最大限度地減少對使用者的影響,他們已經編寫了數百萬個故事和數百個擴充套件,所有這些都基於目前的架構。

那麼,它到底是如何運作的呢?

開始使用 async

在客戶端渲染 RSC 的第一個挑戰是配置如何支援 async 元件。事實證明,Next.js 的 canary React 版本已經 (非官方地) 支援此功能。特別感謝 JamesManningRjulRuss,他們貢獻了這個簡單的解決方案!

import { Suspense } from 'react';

export const ClientContact = ({ id }) => (
  <Suspense><DbCard id={id} /></Suspense>
);

從 Storybook 8 開始,@storybook/nextjs 可以使用 .storybook/main.js 中的 experimentalRSC 功能標誌將您的故事包裝在 Suspense

// .storybook/main.js
export default {
  features: {
    experimentalRSC: true,
  }
};

您也可以在 7.x 版本的 @storybook/nextjs 中手動執行此操作,方法是將您的 RSC 故事包裝在 裝飾器 中。

注意:此解決方案尚無法在其他 Storybook React 框架(例如 react-vitereact-webpack5)中運作,因為它們未使用 Next.js 的 canary 版本 React。希望下一個版本的 React 會消除此限制。

模擬和載入

解決 async 問題僅使我們完成了一半。我們的 DbCard 元件也參考了節點程式碼,該程式碼擷取資料以填充元件。這在瀏覽器中是一個問題,瀏覽器無法執行 Node 程式碼!

為了解決這個問題,我們建議建立一個乾淨的資料存取層。RSC 的架構師也 建議將其作為最佳實務

建立資料存取層後,您可以模擬它,使其可以在瀏覽器中執行,並且您可以精確控制它返回的資料,以練習不同的 UI 狀態(載入中、錯誤、成功等)。

您可以使用模組模擬網路模擬來模擬資料存取層,Storybook 都支援這兩種模擬。

模組:有一個社群擴充套件 storybook-addon-module-mock,它提供 jest.mock 樣式的模擬(僅適用於 Webpack 專案)。您也可以使用 webpack/vite 別名來獲得更簡單但更有限的解決方案。我們計劃在未來版本的 Storybook 中提供符合人體工學的模組模擬。

網路 API:為了模擬網路請求,我們建議使用 Mock Service Worker (msw)。Storybook 也支援許多其他 網路GraphQL 模擬擴充套件。

回到我們的範例,以下是使用 storybook-addon-module-mock 的故事可能看起來的樣子

// DbCard.stories.js

import { 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];
      },
    },
  },
}

完整示範:API + 模組模擬

對於上面的完整範例,包括模組模擬資料庫版本和 MSW2 模擬 API 版本,請查看 我們的完整 RSC 示範 Storybook其 GitHub 儲存庫

A contact card for Chuck Norris (with the email address gmail@chucknorris.com), demonstrated within Storybook

有什麼問題?

在這篇文章中,我們成功地為 Storybook 中的第一個 RSC 編寫了一個故事,並展示了這一切是如何在底層實作的。

這一切都很簡單明瞭,但這種方法有局限性

  1. 逼真度。純客戶端實作與在您的應用程式中執行的伺服器端串流 RSC 實作截然不同。
  2. 便利性。此處的模擬解決方案肯定可以改進。我們目前的模組模擬解決方案不僅冗長,而且與 Storybook args/controls 不相容。

我們計劃在後續迭代中解決這兩個限制,這就是我們將此解決方案標記為實驗性的原因。

立即使用 Storybook for RSC 🎊

若要使用 Storybook for RSC,請將您的 Storybook 升級到 8.0-alpha

npx storybook@next upgrade --prerelease

然後,在您的 .storybook/main.ts 中啟用實驗性功能

// .storybook/main.js
export default {
  features: {
    experimentalRSC: true,
  },
};

如需更多資訊,請參閱 @storybook/nextjs 文件

這是我們詳細介紹 Storybook 8.0(我們的下一個主要版本)內容的第一篇文章,我們將在未來幾個月內推出更多內容。請在 社群媒體上追蹤我們註冊 Storybook 電子報,以隨時掌握有關下一個版本的所有新聞!

加入 Storybook 電郵列表

取得最新消息、更新和版本

6,730位開發人員且持續增加中

我們正在徵人!

加入 Storybook 和 Chromatic 背後的團隊。建構供數十萬開發人員在生產環境中使用的工具。優先考慮遠端工作。

查看職位

熱門文章

如何將 Storybook 速度提高 2-4 倍

最佳化 Storybook 7.6 的建置效能
loading
Kasper Peulen

2024 年 Storybook 的未來

2023 年的重點和即將到來的內容
loading
Michael Shilman

建置您自己的 Storybook GPT

為您的元件自動產生故事
loading
Joe Vaughan
加入社群
6,730位開發人員且持續增加中
為何為何選擇 Storybook元件驅動 UI
文件指南教學課程變更日誌遙測
社群擴充套件參與其中部落格
展示探索專案元件詞彙表
開放原始碼軟體
Storybook - Storybook 繁體中文

特別感謝 Netlify CircleCI