Storybook 安装与配置 #

安装方式 #

自动安装(推荐) #

在现有项目中快速安装 Storybook:

bash
# 进入项目目录
cd my-project

# 自动安装 Storybook
npx storybook@latest init

安装过程会:

text
┌─────────────────────────────────────────────────────────────┐
│                    自动安装流程                              │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  1. 检测项目框架                                            │
│     ├── React                                              │
│     ├── Vue                                                │
│     ├── Angular                                            │
│     ├── Svelte                                             │
│     └── Web Components                                     │
│                                                             │
│  2. 安装依赖                                                │
│     ├── @storybook/react                                   │
│     ├── @storybook/addon-essentials                        │
│     └── 其他必需依赖                                        │
│                                                             │
│  3. 创建配置文件                                            │
│     ├── .storybook/main.js                                 │
│     ├── .storybook/preview.js                              │
│     └── 示例 Stories                                       │
│                                                             │
│  4. 添加脚本命令                                            │
│     ├── storybook (启动开发服务器)                          │
│     └── build-storybook (构建静态站点)                      │
│                                                             │
└─────────────────────────────────────────────────────────────┘

手动安装 #

如果需要更多控制,可以手动安装:

bash
# 安装核心依赖
npm install --save-dev @storybook/react @storybook/react-webpack5

# 安装必需插件
npm install --save-dev @storybook/addon-essentials

# 创建配置目录
mkdir -p .storybook

不同框架的安装 #

React 项目 #

bash
# React + Webpack
npx storybook@latest init --builder webpack5

# React + Vite
npx storybook@latest init --builder vite

Vue 项目 #

bash
# Vue 3
npx storybook@latest init

# Vue 2(需要指定版本)
npm install --save-dev @storybook/vue@6

Angular 项目 #

bash
npx storybook@latest init

Svelte 项目 #

bash
npx storybook@latest init

项目结构 #

安装完成后,项目结构如下:

text
my-project/
├── .storybook/
│   ├── main.js           # 主配置文件
│   ├── preview.js        # 预览配置
│   └── theme.js          # 主题配置(可选)
├── src/
│   ├── components/
│   │   ├── Button.jsx
│   │   └── Button.stories.jsx
│   └── stories/
│       └── Introduction.stories.mdx
└── package.json

配置文件详解 #

main.js - 主配置文件 #

主配置文件定义 Storybook 的核心行为:

javascript
// .storybook/main.js

/** @type { import('@storybook/react-vite').StorybookConfig } */
const config = {
  // Stories 文件位置
  stories: [
    '../src/**/*.mdx',
    '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)',
  ],

  // 插件配置
  addons: [
    '@storybook/addon-links',
    '@storybook/addon-essentials',
    '@storybook/addon-interactions',
  ],

  // 文档配置
  docs: {
    autodocs: 'tag',
  },

  // 构建工具
  framework: {
    name: '@storybook/react-vite',
    options: {},
  },

  // Vite 配置(如果使用 Vite)
  async viteFinal(config) {
    return {
      ...config,
      // 自定义 Vite 配置
    };
  },
};

export default config;

配置选项详解 #

stories - Stories 文件路径 #

javascript
stories: [
  // MDX 文档
  '../src/**/*.mdx',
  
  // Stories 文件
  '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)',
  
  // 特定目录
  '../src/components/**/*.stories.@(js|jsx|ts|tsx)',
],

addons - 插件配置 #

javascript
addons: [
  // 核心插件集合
  '@storybook/addon-essentials',
  
  // 交互测试
  '@storybook/addon-interactions',
  
  // 链接插件
  '@storybook/addon-links',
  
  // 带选项的插件
  {
    name: '@storybook/addon-docs',
    options: {
      configureJSX: true,
    },
  },
],

framework - 框架配置 #

javascript
// React + Vite
framework: {
  name: '@storybook/react-vite',
  options: {},
},

// React + Webpack
framework: {
  name: '@storybook/react-webpack5',
  options: {},
},

// Vue 3 + Vite
framework: {
  name: '@storybook/vue3-vite',
  options: {},
},

// Angular
framework: {
  name: '@storybook/angular',
  options: {},
},

preview.js - 预览配置 #

预览文件用于配置全局设置:

javascript
// .storybook/preview.js

/** @type { import('@storybook/react').Preview } */
const preview = {
  // 全局参数
  parameters: {
    // 布局配置
    layout: 'centered',
    
    // 背景配置
    backgrounds: {
      default: 'light',
      values: [
        { name: 'light', value: '#ffffff' },
        { name: 'dark', value: '#333333' },
        { name: 'brand', value: '#1890ff' },
      ],
    },
    
    // 视口配置
    viewport: {
      viewports: {
        mobile: {
          name: 'Mobile',
          styles: { width: '375px', height: '812px' },
        },
        tablet: {
          name: 'Tablet',
          styles: { width: '768px', height: '1024px' },
        },
        desktop: {
          name: 'Desktop',
          styles: { width: '1280px', height: '800px' },
        },
      },
    },
    
    // 操作配置
    actions: { argTypesRegex: '^on[A-Z].*' },
    
    // 控件配置
    controls: {
      matchers: {
        color: /(background|color)$/i,
        date: /Date$/i,
      },
    },
  },

  // 全局装饰器
  decorators: [
    (Story) => (
      <div style={{ margin: '1em' }}>
        <Story />
      </div>
    ),
  ],

  // 全局类型定义
  argTypes: {
    // 全局参数类型
  },

  // 标签
  tags: ['autodocs'],
};

export default preview;

TypeScript 支持 #

配置 TypeScript #

javascript
// .storybook/main.js
const config = {
  typescript: {
    // 检查类型错误
    check: false,
    
    // React Docgen 配置
    reactDocgen: 'react-docgen-typescript',
    reactDocgenTypescriptOptions: {
      shouldExtractLiteralValuesFromEnum: true,
      propFilter: (prop) => 
        prop.parent ? !/node_modules/.test(prop.parent.fileName) : true,
    },
  },
};

类型定义 #

typescript
// .storybook/main.ts
import type { StorybookConfig } from '@storybook/react-vite';

const config: StorybookConfig = {
  stories: ['../src/**/*.stories.@(js|jsx|ts|tsx|mdx)'],
  addons: ['@storybook/addon-essentials'],
  framework: {
    name: '@storybook/react-vite',
    options: {},
  },
};

export default config;
typescript
// .storybook/preview.ts
import type { Preview } from '@storybook/react';

const preview: Preview = {
  parameters: {
    actions: { argTypesRegex: '^on[A-Z].*' },
    controls: {
      matchers: {
        color: /(background|color)$/i,
        date: /Date$/i,
      },
    },
  },
};

export default preview;

构建工具配置 #

Vite 配置 #

javascript
// .storybook/main.js
const config = {
  async viteFinal(config) {
    // 合并自定义配置
    return {
      ...config,
      resolve: {
        ...config.resolve,
        alias: {
          ...config.resolve?.alias,
          '@': path.resolve(__dirname, '../src'),
        },
      },
      css: {
        ...config.css,
        modules: {
          localIdentName: '[name]__[local]--[hash:base64:5]',
        },
      },
    };
  },
};

Webpack 配置 #

javascript
// .storybook/main.js
const config = {
  webpackFinal: async (config) => {
    // 修改 webpack 配置
    config.module.rules.push({
      test: /\.scss$/,
      use: ['style-loader', 'css-loader', 'sass-loader'],
    });

    // 添加别名
    config.resolve.alias = {
      ...config.resolve.alias,
      '@': path.resolve(__dirname, '../src'),
    };

    return config;
  },
};

环境变量 #

配置环境变量 #

javascript
// .storybook/main.js
const config = {
  env: (config) => ({
    ...config,
    API_URL: process.env.API_URL || 'https://api.example.com',
    FEATURE_FLAG: process.env.FEATURE_FLAG || 'false',
  }),
};

使用环境变量 #

javascript
// .storybook/preview.js
const preview = {
  parameters: {
    API_URL: process.env.API_URL,
  },
};
bash
# 启动时设置环境变量
API_URL=https://dev.api.com npm run storybook

主题定制 #

自定义主题 #

javascript
// .storybook/theme.js
import { create } from '@storybook/theming';

export default create({
  // 基础主题
  base: 'light',

  // 品牌颜色
  colorPrimary: '#1890ff',
  colorSecondary: '#52c41a',

  // UI 颜色
  appBg: '#ffffff',
  appContentBg: '#ffffff',
  appBorderColor: '#e8e8e8',
  appBorderRadius: 4,

  // 文字颜色
  textColor: '#333333',
  textInverseColor: '#ffffff',

  // 工具栏
  barTextColor: '#999999',
  barSelectedColor: '#1890ff',
  barBg: '#ffffff',

  // 品牌标识
  brandTitle: 'My Component Library',
  brandUrl: 'https://example.com',
  brandImage: '/logo.svg',
});

应用主题 #

javascript
// .storybook/manager.js
import { addons } from '@storybook/manager-api';
import theme from './theme';

addons.setConfig({
  theme: theme,
});

启动命令 #

开发模式 #

bash
# 启动开发服务器
npm run storybook

# 或使用 npx
npx storybook dev

# 指定端口
npx storybook dev -p 6007

# 指定主机
npx storybook dev -h 0.0.0.0

# 静态文件目录
npx storybook dev -s ./public

构建静态站点 #

bash
# 构建静态文件
npm run build-storybook

# 或使用 npx
npx storybook build

# 指定输出目录
npx storybook build -o dist-storybook

# 静态文件目录
npx storybook build -s ./public

package.json 脚本 #

json
{
  "scripts": {
    "storybook": "storybook dev -p 6006",
    "build-storybook": "storybook build",
    "test-storybook": "test-storybook",
    "test-storybook:ci": "concurrently -k -s first \"npm run storybook\" \"wait-on http://localhost:6006 && npm run test-storybook\""
  }
}

常见问题 #

1. 模块解析问题 #

javascript
// .storybook/main.js
const config = {
  viteFinal: async (config) => {
    config.resolve = {
      ...config.resolve,
      alias: {
        '@': path.resolve(__dirname, '../src'),
        '@components': path.resolve(__dirname, '../src/components'),
      },
    };
    return config;
  },
};

2. CSS 模块问题 #

javascript
// .storybook/main.js
const config = {
  viteFinal: async (config) => {
    config.css = {
      ...config.css,
      modules: {
        localIdentName: '[name]__[local]--[hash:base64:5]',
      },
    };
    return config;
  },
};

3. 全局样式导入 #

javascript
// .storybook/preview.js
import '../src/styles/global.css';
import '../src/styles/variables.css';

const preview = {
  // ...
};

export default preview;

4. Context Provider 配置 #

javascript
// .storybook/preview.js
import { ThemeProvider } from '../src/theme';
import { I18nProvider } from '../src/i18n';

const preview = {
  decorators: [
    (Story) => (
      <ThemeProvider>
        <I18nProvider>
          <Story />
        </I18nProvider>
      </ThemeProvider>
    ),
  ],
};

export default preview;

最佳实践 #

1. 配置文件组织 #

text
.storybook/
├── main.js           # 主配置
├── preview.js        # 预览配置
├── manager.js        # 管理器配置
├── theme.js          # 主题配置
└── middleware.js     # 中间件(可选)

2. 环境区分 #

javascript
// .storybook/main.js
const isProduction = process.env.NODE_ENV === 'production';

const config = {
  viteFinal: async (config) => {
    if (isProduction) {
      config.build = {
        ...config.build,
        minify: true,
      };
    }
    return config;
  },
};

3. 性能优化 #

javascript
// .storybook/main.js
const config = {
  features: {
    // 启用快速刷新
    storyStoreV7: true,
  },
  
  core: {
    builder: '@storybook/builder-vite',
  },
};

下一步 #

现在你已经完成了 Storybook 的安装与配置,接下来学习 基础使用 开始编写你的第一个 Story!

最后更新:2026-03-29