参加直播会话:美国东部时间周四上午 11 点,Storybook 9 版本发布及 AMA(你问我答)
文档
Storybook Docs

Vite

Storybook 的 Vite 构建器使用快速的 ESM 打包器 Vite 来打包你的组件和 Stories。

  • 对于使用 Vite 构建的应用:它允许在 Storybook 中复用现有的配置。
  • 对于使用 Webpack 构建的应用:它提供了更快的启动和刷新时间,缺点是你的组件执行环境与应用环境不同。

设置

如果你运行了 npx storybook@latest init 将 Storybook 集成到你的 Vite 应用中,构建器已经为你安装并配置好了。如果需要,你也可以手动启用它。

运行以下命令安装构建器。

npm install @storybook/builder-vite --save-dev

更新你的 Storybook 配置(位于 .storybook/main.js|ts)以包含该构建器。

.storybook/main.js|ts
export default {
  stories: ['../src/**/*.mdx', '../stories/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
  addons: ['@storybook/addon-docs'],
  core: {
    builder: '@storybook/builder-vite', // 👈 The builder enabled here.
  },
};

配置

Storybook 的 Vite 构建器开箱即用地为支持的框架包含了一系列默认配置,这些配置会与你现有的配置文件合并。为了在使用 Vite 构建器时获得最佳体验,我们建议将所有配置直接应用在 Vite 的配置文件(即 vite.config.js|ts)中。

Storybook 加载时,会自动将配置合并到自身配置中。然而,由于不同项目可能有特定要求,你可能需要为 Storybook 提供自定义配置。在这种情况下,你可以修改你的配置文件(.storybook/main.js|ts)并添加 viteFinal 配置函数,如下所示

.storybook/main.js|ts
export default {
  // Replace your-framework with the framework you are using, e.g. react-vite, nextjs-vite, vue3-vite, etc.
  framework: '@storybook/your-framework',
  stories: ['../src/**/*.mdx', '../stories/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
  addons: ['@storybook/addon-docs'],
  core: {
    builder: '@storybook/builder-vite',
  },
  async viteFinal(config) {
    // Merge custom configuration into the default config
    const { mergeConfig } = await import('vite');
 
    return mergeConfig(config, {
      // Add dependencies to pre-optimization
      optimizeDeps: {
        include: ['storybook-dark-mode'],
      },
    });
  },
};

异步函数 viteFinal 接收一个包含默认构建器配置的 config 对象,并返回更新后的配置。

基于环境的配置

如果你需要自定义构建器的配置并根据你的环境应用特定选项,可以扩展 viteFinal 函数,如下所示

.storybook/main.js|ts
export default {
  // Replace your-framework with the framework you are using, e.g. react-vite, nextjs-vite, vue3-vite, etc.
  framework: '@storybook/your-framework',
  stories: ['../src/**/*.mdx', '../stories/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
  core: {
    builder: '@storybook/builder-vite',
  },
  async viteFinal(config, { configType }) {
    const { mergeConfig } = await import('vite');
 
    if (configType === 'DEVELOPMENT') {
      // Your development configuration goes here
    }
    if (configType === 'PRODUCTION') {
      // Your production configuration goes here.
    }
    return mergeConfig(config, {
      // Your environment configuration here
    });
  },
};

覆盖默认配置

默认情况下,Storybook 中的 Vite 构建器会在 Storybook 项目的根目录中搜索 Vite 配置文件。然而,你可以自定义它在其他位置寻找配置文件。例如

.storybook/main.js|ts
export default {
  stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
  core: {
    builder: {
      name: '@storybook/builder-vite',
      options: {
        viteConfigPath: '../customVite.config.js',
      },
    },
  },
};

如果你不希望 Storybook 自动加载 Vite 配置文件,可以使用 viteConfigPath 选项指向一个不存在的文件。

TypeScript

如果需要,你也可以使用 TypeScript 配置 Storybook 的 Vite 构建器。将你的 .storybook/main.js 文件重命名为 .storybook/main.ts 并进行如下调整

.storybook/main.ts
// Replace your-framework with the framework you are using, e.g. react-vite, nextjs-vite, vue3-vite, etc.
import type { StorybookConfig } from '@storybook/your-framework';
 
const config: StorybookConfig = {
  framework: '@storybook/your-framework',
  stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
  async viteFinal(config, options) {
    // Add your configuration here
    return config;
  },
};
 
export default config;

故障排除

从 Webpack 迁移

Vite 通常比 Webpack 开箱即用地处理更多用例。例如,加载样式对大多数项目来说都能正常工作。因此,将基于 Webpack 的项目迁移到 Vite 时,你可能会发现不再需要之前的所有配置。

我们建议从没有 Storybook 特定的 Vite 配置开始,然后只添加你确定项目实际需要的内容。

作为参考,这是一个处理加载 graphql 查询的 Webpack 配置及其在 Vite 中使用插件的等效配置

.storybook/main.ts
// Replace your-framework with the framework you are using (e.g., react-webpack5, nextjs, angular)
import type { StorybookConfig } from '@storybook/your-framework';
 
const config: StorybookConfig = {
  framework: '@storybook/your-framework',
  stories: ['../src/**/*.mdx', '../stories/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
  async webpackFinal(config) {
    config.module?.rules?.push({
      test: /\.(graphql|gql)$/,
      include: [path.resolve('./lib/emails')],
      exclude: /node_modules/,
      loader: 'graphql-tag/loader',
    });
    config.module?.rules?.push({
      test: /\.(graphql|gql)$/,
      include: [path.resolve('./lib/schema')],
      exclude: /node_modules/,
      loader: 'raw-loader',
    });
 
    return config;
  },
};
 
export default config;

工作目录未被检测到

默认情况下,Vite 构建器为了提高安全性,启用了 Vite 的 server.fs.strict 选项,并将项目的 root 定义为 Storybook 的配置目录。如果你需要覆盖它,可以使用 viteFinal 函数进行调整。

ArgTypes 未自动生成

目前,自动 ArgType 推断 仅适用于 React、Vue 3 和 Svelte(仅限 JSDocs)。对于 React,Vite 构建器默认使用 react-docgen,它是解析 React 组件时比 react-docgen-typescript 更快的替代方案。如果你遇到任何问题,可以通过更新 Storybook 配置文件,回退到 react-docgen-typescript,如下所示

.storybook/main.js|ts
export default {
  stories: ['../src/**/*.mdx', '../stories/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
  addons: ['@storybook/addon-docs'],
  core: {
    builder: '@storybook/builder-vite',
  },
  typescript: {
    // Enables the `react-docgen-typescript` parser.
    // See https://storybook.org.cn/docs/api/main-config/main-config-typescript for more information about this option.
    reactDocgen: 'react-docgen-typescript',
  },
};

交互测试未按预期工作

如果你正在将基于 Webpack 的项目(例如 CRA)迁移到 Vite,并且正在进行交互测试,你可能会遇到测试执行失败并提示 window 对象未定义的情况。要解决此问题,可以在 Storybook 配置目录中创建一个 preview-head.html 文件,并包含以下内容

.storybook/preview-head.html
<script>
  window.global = window;
</script>

了解更多关于构建器的信息