框架
Storybook 的架構旨在支援各種 Web 框架,包括 React、Vue、Angular、Web Components、Svelte 和其他十幾個框架。本指南可協助您開始為 Storybook 新增框架支援。
建立新框架的骨架
首先要做的是在自己的儲存庫中建立框架支援的骨架。
我們建議採用與 Storybook 單一儲存庫相同的專案結構。該結構包含框架套件 (app/<框架>
) 和範例應用程式 (examples/<框架>-kitchen-sink
),以及其他相關的文件和設定 (如有需要)。
它看起來可能比必要的層級多一點。但由於此結構反映了 Storybook 單一儲存庫的結構方式,您可以重複使用 Storybook 的工具。如果稍後需要,也可以更輕鬆地將框架移至 Storybook 單一儲存庫中。
我們建議使用 @storybook/html
作為入門框架,因為它是最簡單的,而且不包含任何框架特定的特性。這裡有一個範本可以讓您開始 這裡。
框架架構
在 Storybook 中支援新框架通常包含兩個主要層面
-
設定伺服器。在 Storybook 中,伺服器是在您執行
storybook dev
或storybook build
時執行的節點程序。設定伺服器通常表示以框架特定的方式設定 babel 和 webpack。 -
設定用戶端。用戶端是在瀏覽器中執行的程式碼,而設定用戶端表示提供一個框架特定的 story 渲染函式。
設定伺服器
Storybook 有 預設設定 的概念,這些設定通常是用於檔案載入的 babel/webpack 設定。如果您的框架有自己的檔案格式 (例如,「.vue」),您可能需要在載入時將它們轉換為 JavaScript 檔案。如果您假設您框架的每個使用者都需要這個功能,則應該將其新增至框架。到目前為止,已新增至 Storybook 的每個框架都已完成此動作,因為 Storybook 的核心設定極為精簡。
套件結構
在新增框架預設設定之前,先了解 Storybook 的套件結構會很有幫助。每個框架通常會在其 package.json
中公開兩個可執行檔
{
"bin": {
"storybook": "./bin/index.js",
"build-storybook": "./bin/build.js"
}
}
這些指令碼會將 options
物件傳遞至 @storybook/core/server
,這是一個抽象化所有 Storybook 與框架無關的程式碼的程式庫。
例如,以下是使用 storybook dev
啟動開發伺服器的範本
import { buildDev } from '@storybook/core/server';
import options from './options';
buildDev(options);
因此,新增框架預設設定的精髓就是填寫該選項物件。
伺服器選項
如上所述,伺服器的 options
物件負責伺服器的主要配置工作。
讓我們來看看 @storybook/vue
的選項定義。
import { sync } from 'read-pkg-up';
export default {
packageJson: sync({ cwd: __dirname }).packageJson,
framework: 'vue',
frameworkPresets: [require.resolve('./framework-preset-vue.js')],
};
framework
選項的值(即 'vue')會傳遞給 addons,讓它們可以執行與您的框架相關的特定任務。
此檔案的重點在於框架預設設定,這些是標準的 Storybook 預設設定 -- 您可以查看 Storybook monorepo 中的框架套件(例如 React、 Vue、 Web Components)以查看特定於框架的自訂範例。
在開發您自己、非 Storybook 維護的自訂框架時,您可以使用 frameworkPath
鍵指定位置檔案的路徑。
import { sync } from 'read-pkg-up';
export default {
packageJson: sync({ cwd: __dirname }).packageJson,
framework: 'my-framework',
frameworkPath: '@my-framework/storybook',
frameworkPresets: [require.resolve('./framework-preset-my-framework.js')],
};
您可以將相對路徑新增至 frameworkPath
。別忘了,它們預設會從 Storybook 的設定目錄(即 .storybook
)解析。
請確保 frameworkPath
最後指向您框架應用程式內的 dist/client/index.js
檔案。
設定客戶端
若要設定客戶端,您必須提供一個特定於框架的渲染函式。在深入探討細節之前,必須先了解使用者撰寫的 stories 與螢幕上呈現的內容之間的關聯。
可渲染物件
Storybook stories 是 ES6 物件,會傳回「可渲染物件」。
請考慮以下 React story
import { Button } from './Button';
export default {
component: Button,
};
export const Sample = {
render: () => <Button label="hello button" />,
};
在這種情況下,可渲染物件是 React 元素 <Button .../>
。
在大多數其他框架中,可渲染物件實際上是一個普通的 JavaScript 物件。
請考慮以下假設範例
// Replace your-framework with the name of your framework
import type { Meta, StoryObj } from '@storybook/your-framework';
import { Button } from './Button';
const meta: Meta<typeof Button> = {
component: Button,
};
export default meta;
type Story = StoryObj<typeof Button>;
export const Sample: Story = {
render: () => ({
template: '<button :label=label />',
data: {
label: 'hello button',
},
}),
};
這種「可渲染物件」的設計是特定於框架的,理想情況下應符合該框架的慣用語。
渲染函式
框架的渲染函式負責將可渲染物件轉換為 DOM 節點。它通常具有以下形式
const rootElement = document.getElementById('root');
export default function renderMain({ storyFn }: RenderMainArgs) {
const storyObj = storyFn();
const html = fn(storyObj);
rootElement.innerHTML = html;
}
套件結構
在客戶端,關鍵檔案是 src/client/preview.js
import { start } from '@storybook/preview-api';
import './globals';
import render from './render';
const api = start(render);
// the boilerplate code
全域檔案通常會設定一個全域變數,以便客戶端程式碼(例如附加元件提供的裝飾器)在需要時可以參考,以了解它在哪個框架中執行。
import { global } from '@storybook/global';
const { window: globalWindow } = global;
globalWindow.STORYBOOK_ENV = 'vue';
start
函式抽象化了所有 Storybook 獨立於框架的客戶端(瀏覽器)程式碼,並且它會採用我們在上方定義的渲染函式。如需渲染函式的範例,請參閱 Storybook monorepo 中的 React、 Vue、 Angular 和 Web Components。