文件
Storybook 文件

編寫預設組件

Storybook 預設組件是預先配置的設定或組態,讓開發人員能夠快速設定並自訂其環境,並包含一組特定的功能、特性或整合。

預設組件如何運作

預設組件允許開發人員透過 API 組成各種配置選項和外掛程式,以整合 Storybook 並自訂其行為和功能。一般來說,預設組件會分成兩個檔案,每個檔案都有其特定的角色。

本機預設組件

這種類型的預設組件可讓您封裝和組織特定於組件的配置,包括建構器支援、Babel 或第三方整合。例如

example-addon/src/preset.ts
import { webpackFinal as webpack } from './webpack/webpackFinal';
 
import { viteFinal as vite } from './vite/viteFinal';
 
import { babelDefault as babel } from './babel/babelDefault';
 
export const webpackFinal = webpack as any;
 
export const viteFinal = vite as any;
 
export const babelDefault = babel as any;

根層級預設組件

這種類型的預設組件是面向使用者的,負責註冊組件,而無需使用者進行任何額外的配置,方法是透過 previewAnnotations 捆綁 Storybook 相關的功能(例如,parameters),並透過 managerEntries API 捆綁 UI 相關的功能(例如,組件)。例如

example-addon/preset.js
export const previewAnnotations = [require.resolve('./dist/preview')];
 
export const managerEntries = [require.resolve('./dist/manager')];
 
export * from './dist/preset';

預設組件 API

在編寫預設組件時,您可以存取一組選定的 API,與 Storybook 環境互動,包括支援的建構器(例如,Webpack、Vite)、Storybook 配置和 UI。以下是編寫預設組件時可用的 API。

Babel

若要自訂 Storybook 的 Babel 配置並新增對其他功能的支援,您可以使用 babelDefault API。它會在任何其他使用者預設組件之前套用提供的配置,最終使用者可以透過 babel 配置選項進一步自訂。例如

example-addon/src/babel/babelDefault.ts
import { TransformOptions } from '@babel/core';
 
export function babelDefault(config: TransformOptions) {
  return {
    ...config,
    plugins: [
      ...config.plugins,
      [require.resolve('@babel/plugin-transform-react-jsx'), {}, 'preset'],
    ],
  };
}

Babel 配置僅適用於內部使用 Babel 的框架。如果您為使用不同編譯器(例如 SWCesbuild)的框架啟用它,則會被忽略。

建構器

預設情況下,Storybook 支援業界領先的建構器,包括 WebpackVite。如果您需要這些建構器的其他功能,可以使用 API 來擴展建構器配置,以滿足您的特定需求。

Vite

如果您正在建立預設組件並想要包含 Vite 支援,則可以使用 viteFinal API 修改預設配置並啟用其他功能。例如

example-addon/src/vite/viteFinal.ts
export function ViteFinal(config: any, options: any = {}) {
  config.plugins.push(
    new MyCustomPlugin({
      someOption: true,
    }),
  );
 
  return config;
}

Webpack

若要自訂 Storybook 中的 Webpack 配置,以新增對其他檔案類型的支援、套用特定的 loaders、配置外掛程式或進行任何其他必要的修改,您可以使用 webpackFinal API。一旦調用,它將使用提供的配置擴展預設的 Webpack 配置。一個例子是

example-addon/src/webpack/webpackFinal.ts
import type { Configuration as WebpackConfig } from 'webpack';
 
export function webpackFinal(config: WebpackConfig, options: any = {}) {
  const rules = [
    ...(config.module?.rules || []),
    {
      test: /\.custom-file$/,
      loader: require.resolve(`custom-loader`),
    },
  ];
  config.module.rules = rules;
 
  return config;
}

ManagerEntries

如果您正在編寫一個預設組件,用於載入您可能無法控制的第三方組件,但需要存取特定功能或額外配置,則可以使用 managerEntries API。例如

example-addon/preset.js
export const managerEntries = (entry = []) => {
  return [...entry, require.resolve('path-to-third-party-addon')];
};

PreviewAnnotations

如果您需要其他設定來為預設組件渲染 stories,例如 decorators 或 parameters,您可以使用 previewAnnotations API。例如,若要將 decorator 套用到所有 stories,請建立一個包含 decorator 的預覽檔案,並使其可供預設組件使用,如下所示

example-addon/src/preview.ts
import type { Renderer, ProjectAnnotations } from '@storybook/types';
import { PARAM_KEY } from './constants';
import { CustomDecorator } from './decorators';
 
const preview: ProjectAnnotations<Renderer> = {
  decorators: [CustomDecorator],
  globals: {
    [PARAM_KEY]: false,
  },
};
 
export default preview;

進階配置

預設組件 API 旨在具有彈性,並允許您根據特定需求自訂 Storybook,包括在更進階的使用案例中使用預設組件,而無需發布它們。在這種情況下,您可以依賴私有預設組件。這些私有預設組件包含用於開發目的而非最終使用者的配置選項。.storybook/main.js|ts 檔案就是這樣一個私有預設組件的範例,它可以讓您修改 Storybook 的行為和功能。

.storybook/main.ts
// Replace your-framework with the framework you are using (e.g., react-webpack5, vue3-vite)
import type { StorybookConfig } from '@storybook/your-framework';
 
const config: StorybookConfig = {
  viteFinal: async (config, options) => {
    // Update config here
    return config;
  },
  webpackFinal: async (config, options) => {
    // Change webpack config
    return config;
  },
  babel: async (config, options) => {
    return config;
  },
};
 
export default config;

組件

對於組件消費者來說,managerEntries API 可能太過技術性,難以使用。為了讓將組件新增到 Storybook 更容易,預設組件 API 提供了 addons API,它接受組件名稱的陣列,並會自動為您載入它們。例如

.storybook/main.ts
// Replace your-framework with the framework you are using (e.g., react-webpack5, vue3-vite)
import type { StorybookConfig } from '@storybook/your-framework';
 
const config: StorybookConfig = {
  addons: [
    // Other Storybook addons
    '@storybook/addon-a11y',
  ],
};
 
export default config;

值陣列支援對應到應包含在管理器中的其他預設組件和組件的參考。Storybook 將自動偵測提供的值是預設組件還是組件,並相應地載入它。

Entries

Entries 是註冊預覽的進入點的地方。此功能可用於建立一個 configure-storybook 預設組件,該組件會自動將所有 *.stories.js 檔案載入到 Storybook 中,從而消除使用者重複複製貼上相同配置的需求。

UI 配置

Storybook 預設組件 API 也提供對 UI 配置的存取,包括預覽的 headbody HTML 元素,這些元素由 previewHeadpreviewBody API 配置。兩者都允許您以類似於使用 preview-head.htmlpreview-body.html 檔案的方式設定 Storybook。這些方法接受字串並傳回修改後的版本,將提供的內容注入到 HTML 元素中。

.storybook/main.ts
// Replace your-framework with the framework you are using (e.g., react-webpack5, vue3-vite)
import type { StorybookConfig } from '@storybook/your-framework';
 
const config: StorybookConfig = {
  previewBody: (body) => `
    ${body}
    ${
      process.env.ANALYTICS_ID ? '<script src="https://cdn.example.com/analytics.js"></script>' : ''
    }
  `,
};
 
export default config;

此外,如果您需要自訂管理器(即 Storybook 的搜尋、導航、工具列和組件的渲染位置),您可以使用 managerHead 來修改 UI,類似於您使用 manager-head.html 檔案的方式。例如

.storybook/main.ts
// Replace your-framework with the framework you are using (e.g., react-webpack5, vue3-vite)
import type { StorybookConfig } from '@storybook/your-framework';
 
const config: StorybookConfig = {
  managerHead: (head) => `
    ${head}
    <link rel="icon" type="image/png" href="/logo192.png" sizes="192x192" />
  `,
};
 
export default config;

但是,如果需要,您也可以自訂 Storybook 用於渲染 UI 的範本。為此,您可以使用 previewMainTemplate API 並提供以 ejs 檔案建立的自訂範本的參考。有關如何執行此操作的範例,請參閱 Webpack 5 建構器使用的範本

疑難排解

Storybook 未載入我的預設組件中的檔案

由於 Storybook 依賴 esbuild 而非 Webpack 來建置 UI,因此依賴 managerWebpack API 來配置管理器或載入 CSS 或圖片以外的其他檔案的預設組件將不再運作。我們建議從您的預設組件中移除它,並調整您的配置以將任何其他檔案轉換為 JavaScript。

深入了解 Storybook 組件生態系統