Docs
Storybook Docs

编写预设插件

Storybook 预设是预先配置的设置或配置,使开发者能够使用一组特定的特性、功能或集成快速设置和自定义他们的环境。

¥Storybook presets are pre-configured settings or configurations that enable developers quickly set up and customize their environment with a specific set of features, functionalities, or integrations.

测试构建速度提高 2-4 倍 =

¥How presets work

预设插件允许开发者通过 API 编写各种配置选项和插件,以与 Storybook 集成并自定义其行为和功能。通常,预设分为两个文件,每个文件都有其特定的角色。

¥Preset addons allow developers to compose various configuration options and plugins via APIs to integrate with Storybook and customize its behavior and functionality. Typically, presets are separated into two files, each with its specific role.

本地预设

¥Local presets

这种类型的预设允许你封装和组织特定于插件的配置,包括 builder 支持、Babel 或第三方集成。例如:

¥This type of preset allows you to encapsulate and organize configurations specific to the addon, including builder support, Babel, or third-party integrations. For example:

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;

根级预设

¥Root-level presets

这种类型的预设面向用户,负责通过 previewAnnotations 打包 Storybook 相关功能(例如 参数)并通过 managerEntries API 打包 UI 相关功能(例如插件),无需用户进行任何额外配置即可注册插件。例如:

¥This type of preset is user-facing and responsible for registering the addon without any additional configuration from the user by bundling Storybook-related features (e.g., parameters) via the previewAnnotations and UI related features (e.g., addons) via the managerEntries API. For example:

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

预设 API

¥Presets API

编写预设时,你可以访问一组选定的 API 来与 Storybook 环境交互,包括受支持的构建器(例如 Webpack、Vite)、Storybook 配置和 UI。以下是编写预设插件时可以使用的可用 API。

¥When writing a preset, you can access a select set of APIs to interact with the Storybook environment, including the supported builders (e.g., Webpack, Vite), the Storybook configuration, and UI. Below are the available APIs you can use when writing a preset addon.

Babel

要自定义 Storybook 的 Babel 配置并添加对其他功能的支持,你可以使用 babelDefault API。它将在任何其他用户预设之前应用提供的配置,终端用户可以通过 babel 配置选项进一步自定义这些预设。例如:

¥To customize Storybook's Babel configuration and add support for additional features, you can use the babelDefault API. It will apply the provided configuration ahead of any other user presets, which can be further customized by the end user via the babel configuration option. For example:

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)启用它,它将被忽略。

¥The Babel configuration is only applied to frameworks that use Babel internally. If you enable it for a framework that uses a different compiler, like SWC or esbuild, it will be ignored.

构建器

¥Builders

默认情况下,Storybook 为领先的行业构建器提供支持,包括 WebpackVite。如果你需要任何这些构建器的其他功能,则可以使用 API 根据你的特定需求扩展构建器配置。

¥By default, Storybook provides support for the leading industry builders, including Webpack and Vite. If you need additional features for any of these builders, you can use APIs to extend the builder configuration based on your specific needs.

Vite

如果你正在创建预设并希望包含 Vite 支持,则可以使用 viteFinal API 来修改默认配置并启用其他功能。例如:

¥If you are creating a preset and want to include Vite support, the viteFinal API can be used to modify the default configuration and enable additional features. For example:

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 配置以添加对其他文件类型的支持、应用特定的加载器、配置插件或进行任何其他必要的修改,你可以使用 webpackFinal API。一旦调用,它将使用提供的配置扩展默认的 Webpack 配置。例如:

¥To customize the Webpack configuration in Storybook to add support for additional file types, apply specific loaders, configure plugins, or make any other necessary modifications, you can use the webpackFinal API. Once invoked, it will extend the default Webpack configuration with the provided configuration. An example of this would be:

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。例如:

¥If you're writing a preset that loads third-party addons, which you may not have control over, but require access to specific features or additional configuration, you can use the managerEntries API. For example:

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

PreviewAnnotations

如果你需要其他设置来为预设(如 decorators参数)渲染故事,则可以使用 previewAnnotations API。例如,要将装饰器应用于所有故事,请创建包含装饰器的预览文件并将其提供给预设,如下所示:

¥If you need additional settings to render stories for a preset, like decorators or parameters, you can use the previewAnnotations API. For example, to apply a decorator to all stories, create a preview file that includes the decorator and make it available to the preset as follows:

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;

高级配置

¥Advanced configuration

预设 API 旨在灵活,允许你根据特定需求自定义 Storybook,包括使用预设进行更高级的用例而无需发布它们。在这种情况下,你可以依赖私有预设。这些私有预设包含用于开发目的而不是终端用户的配置选项。.storybook/main.js|ts 文件是此类私有预设的示例,它使你能够修改 Storybook 的行为和功能。

¥The presets API is designed to be flexible and allow you to customize Storybook to your specific needs, including using presets for more advanced use cases without publishing them. In such cases, you can rely on a private preset. These private presets contain configuration options meant for development purposes and not for end-users. The .storybook/main.js|ts file is an example of such a private preset that empowers you to modify the behavior and functionality of 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;

插件

¥Addons

对于插件消费者,managerEntries API 可能过于技术化,难以使用。为了更轻松地将插件添加到 Storybook,预设 API 提供了 addons API,它接受插件名称数组并会自动为你加载它们。例如:

¥For addon consumers, the managerEntries API can be too technical, making it difficult to use. To make it easier to add addons to Storybook, the preset API provides the addons API, which accepts an array of addon names and will automatically load them for you. For example:

.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 将自动检测提供的值是预设还是插件,并相应地加载它。

¥The array of values supports references to additional presets and addons that should be included in the manager. Storybook will automatically detect whether the provided value is a preset or an addon and load it accordingly.

条目

¥Entries

条目是注册预览入口点的地方。此功能可用于创建一个 configure-storybook 预设,该预设会自动将所有 *.stories.js 文件加载到 Storybook 中,无需用户重复复制粘贴相同的配置。

¥Entries are the place to register entry points for the preview. This feature can be utilized to create a configure-storybook preset that automatically loads all *.stories.js files into Storybook, eliminating the need for users to copy-paste the same configuration repeatedly.

UI 配置

¥UI configuration

Storybook 预设 API 还提供对 UI 配置的访问,包括由 previewHeadpreviewBody API 配置的预览的 headbody HTML 元素。两者都允许你以类似于使用 preview-head.htmlpreview-body.html 文件的方式设置 Storybook。这些方法接受字符串并返回修改后的版本,将提供的内容注入 HTML 元素。

¥The Storybook preset API also provides access to the UI configuration, including the head and body HTML elements of the preview, configured by the previewHead and previewBody APIs. Both allow you to set up Storybook in a way that is similar to using the preview-head.html and preview-body.html files. These methods accept a string and return a modified version, injecting the provided content into the HTML element.

.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 文件的操作。例如:

¥Additionally, if you need to customize the manager (i.e., where Storybook’s search, navigation, toolbars, and addons render), you can use the managerHead to modify the UI, similar to how you would do it with the manager-head.html file. For example:

.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 构建器使用的 template

¥However, if you need, you can also customize the template used by Storybook to render the UI. To do so, you can use the previewMainTemplate API and provide a reference for a custom template created as a ejs file. For an example of how to do this, see the template used by the Webpack 5 builder.

故障排除

¥Troubleshooting

Storybook 不会加载我的预设中的文件

¥Storybook doesn't load files in my preset

由于 Storybook 依赖 esbuild 而不是 Webpack 来构建 UI,因此依赖于 managerWebpack API 来配置管理器或加载除 CSS 或图片之外的其他文件的预设将不再起作用。我们建议将其从你的预设中删除,并调整你的配置以将任何其他文件转换为 JavaScript。

¥As Storybook relies on esbuild instead of Webpack to build the UI, presets that depend on the managerWebpack API to configure the manager or load additional files other than CSS or images will no longer work. We recommend removing it from your preset and adjusting your configuration to convert any additional files to JavaScript.

了解有关 Storybook 插件生态系统的更多信息

¥Learn more about the Storybook addon ecosystem