Storybook viteFinal 配置实战:自定义 Vite 构建器的开发与生产配置
发布时间:2026/9/8 17:16:27来源:尧图网络
Storybook viteFinal 配置实战自定义 Vite 构建器的开发与生产配置【免费下载链接】storybookStorybook is the industry standard workshop for building, documenting, and testing UI components in isolation项目地址: https://gitcode.com/GitHub_Trending/st/storybookStorybook 官方文档将viteFinal定义为 Vite builder 场景下的配置入口函数用于在 Storybook 的 Vite 构建管线中注入自定义配置。本篇以 main-config-vite-final.md 中提供的完整代码骨架为主体结合 viteFinal API 参考、Vite 构建器指南以及storybook/builder-vite的真实实现源码讲解viteFinal的签名、调用时机、环境区分写法与底层原理。读完本文你将能够在自己项目的.storybook/main.js|ts中写出类型安全、可区分开发/生产环境的 Vite 定制逻辑并理解为何要用mergeConfig合并配置。viteFinal 是什么main 配置中的 Vite 定制钩子当 Storybook 使用 Vite builder 打包组件与 stories 时Vite 是当前 Storybook 的默认 builder代码见 code/builders/builder-vite框架已经为受支持的各类框架内置了一套 Vite 配置默认值并将其与你项目中已有的vite.config.js|ts自动合并。官方推荐能用 Vite 自身配置文件解决的问题优先直接在 Vite 配置文件内完成只有当 Storybook 场景需要额外定制时才在 .storybook/main.js|ts 中通过viteFinal追加配置。依据 viteFinal API 参考其完整类型签名如下(config: Vite.InlineConfig, options: Options) Vite.InlineConfig | PromiseVite.InlineConfig // Options 类型为 // { configType?: DEVELOPMENT | PRODUCTION }viteFinal是一个异步函数它接收 Vite builder 组装好的默认config对象经过你的改造后返回或异步返回最终生效的配置。这种接收默认配置→修改→返回的设计使它对已有的默认配置是追加式定制而不是另起炉灶重写一套构建配置。它在构建管线中的真实调用位置从storybook/builder-vite源码可以确认viteFinal并非魔法钩子而是通过 Storybook 的 preset 管线统一执行的开发服务器在 code/builders/builder-vite/src/vite-server.ts 中创建 Vite dev server 前执行presets.apply(viteFinal, config, options)生产构建在 code/builders/builder-vite/src/build.ts 中调用 Vite 的build前执行同样的presets.apply(viteFinal, config, options)无头工具链在 code/builders/builder-vite/src/change-detection-adapter/headless.ts 中storybook tools这类无需 dev server 的场景同样按先commonConfig(options, development)再套用viteFinal的顺序组装配置。也就是说你在viteFinal中写下的逻辑会同时作用于本地开发、storybook build生产构建以及依赖同一套配置解析的工具场景。测试代码 vite-config.test.ts 中configType: DEVELOPMENT的用例也印证了configType这一参数的真实形态。顺带一提Storybook 的遥测模块会检测 main 配置中是否存在viteFinal并记录hasCustomVite元数据相关实现见 code/core/src/telemetry/storybook-metadata.ts。最小可用骨架在 main 配置中声明 viteFinal下面是与关联文档一致的完整最小骨架.storybook/main.js展示了viteFinal的标准用法动态导入 Vite 的mergeConfig用configType区分环境最后合并并返回配置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)], 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 }); }, };其中三个要点configType由框架注入取值为DEVELOPMENT或PRODUCTION分别对应storybook dev与storybook build两个命令的运行环境configType在 transform-iframe-html.ts 中同样被用于区分两种模式下的 HTML 模板处理mergeConfig是从vite包动态导入的工具函数它按 Vite 的语义深度合并配置对象是官方示例中推荐的合并方式。直接用对象展开{ ...config, ...myConfig }会丢失嵌套键如resolve.alias、plugins数组framework需替换为实际安装的框架包名例如storybook/react-vite、storybook/vue3-vite、storybook/nextjs-vite、storybook/web-components-vite等对应仓库 code/frameworks 下各 Vite 系框架目录。TypeScript 版本若项目使用 TypeScript可将.storybook/main.js重命名为.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, ../stories/**/*.stories.(js|jsx|mjs|ts|tsx)], 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 }); }, }; export default config;CSF Next实验性写法defineMainStorybook 较新版本提供了实验性的 CSF Next 配置写法通过从storybook/framework/node导入defineMain来声明 main 配置。由于defineMain接收完整的泛型configType等回调参数能够获得自动类型推断无需手写StorybookConfigimport { defineMain } from storybook/vue3-vite/node; export default defineMain({ framework: storybook/vue3-vite, stories: [../src/**/*.mdx, ../stories/**/*.stories.(js|jsx|mjs|ts|tsx)], 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 }); }, });对应不同框架时仅需替换包名与framework字段例如storybook/web-components-vite/nodestorybook/web-components-vite或 React 生态下的storybook/react-vite/node。CSF Next 写法主要面向新项目与框架新版本两种风格在功能上是等价的。分环境定制开发与生产的差异化配置Options.configType的取值直接告诉你当前是哪种模式配合 if 分支即可做到互不干扰的差异化定制典型场景包括DEVELOPMENT放宽性能限制、注入仅本地需要的 mock 插件、调整server相关配置以加速热更新PRODUCTION压缩代码、剔除仅调试用的依赖、设置面向静态托管如 Chromatic的输出相关选项。这与 viteFinal API 参考 中给出的 Options 类型{ configType?: DEVELOPMENT | PRODUCTION }完全对应。API 参考同时注明Options还包含一些难以在文档中一一列出的其余字段如需穷举可自行查看类型定义文件。需要留意的是环境定制不应违背能不改就不改的原则。Vite 构建器指南 明确指出 Vite 相比 Webpack 开箱即用能力更强如样式加载多数项目无需配置Webpack 迁移场景建议先以零 Storybook 专属 Vite 配置起步再按实际需求逐项补充。真实场景alias、依赖预构建与配置合并上文骨架只是框架落到实际需要把viteFinal与mergeConfig用起来。以下是从 storybook-vite-builder-aliasing.md 摘取的代表性示例——将storybook-dark-mode这类依赖加入 Vite 的optimizeDeps.include预构建白名单以规避暗色主题等依赖在开发模式下的预构建报错import type { StorybookConfig } from storybook/your-framework; const config: StorybookConfig { framework: storybook/your-framework, stories: [../src/**/*.mdx, ../stories/**/*.stories.(js|jsx|mjs|ts|tsx)], 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], }, }); }, }; export default config;当项目以 Vite 应用为基底时viteFinal常与resolve.alias等 Vite 配置联动先在应用的vite.config.ts中统一维护路径别名再在viteFinal中按需向 Storybook 的 config 追加官方建议一切能放vite.config的配置优先放在那里因为 Storybook 加载时会自动合并它。如果明确用不到vite.config之外的定制viteFinal也可以完全省略。相关配套能力viteConfigPath 与 configLoaderviteFinal定制的是配置内容而以下两个 builder 选项定制的则是配置来源与加载方式三者常被放在一起讨论viteConfigPath默认 builder 会在 Storybook 项目根目录查找 Vite 配置文件若希望读取其他位置的配置文件或完全禁用自动加载——只需把viteConfigPath指向一个不存在的文件可在core.builder的对象形态中声明完整示例见 main-config-builder-custom-config.mdexport default { stories: [../src/**/*.mdx, ../src/**/*.stories.(js|jsx|mjs|ts|tsx)], core: { builder: { name: storybook/builder-vite, options: { viteConfigPath: ../customVite.config.js, }, }, }, };configLoader通过 builder options 或等价命令行参数--configLoader传入交给 Vite 决定配置文件用何种方式加载如 bundle 或 native详见 Vite 构建器指南 中 Set configLoader for vite config 一节与 main-config-builder-configLoader.md。Vite 支持的合法取值需查阅 Vite 官方配置文档。底层机制commonConfig → viteFinal 的两段式组装结合源码可以看到viteFinal之所以能拿到一份可继续加工的默认配置是因为 builder 内部采用了清晰的两段式组装commonConfig(options, mode)先生成包含框架默认值、Stories 入口、插件等内容的基线配置开发模式下 mode 为development生产模式对应build见 vite-config.test.ts 对commonConfigMock的断言随后presets.apply(viteFinal, config, options)把你的定制逻辑串接到这条 preset 链的末端。因此你在viteFinal中拿到的config已经是Storybook 视角的完整基线mergeConfig负责把新增项正确地融合进去最终交回 Vite。这套机制也解释了为何 Vite 构建器指南 在工作目录未被正确识别等故障排查场景中建议直接用viteFinal覆盖默认行为——例如当server.fs.strict与配置文件根目录的默认推断与你项目实际布局冲突时viteFinal就是唯一且对口的调整点。小结与最佳实践围绕viteFinal建议遵循以下实践默认优先通用 Vite 配置尽量放在vite.config.js|tsStorybook 会自动合并viteFinal只放 Storybook 专属定制用 mergeConfig 合并官方示例统一从vite动态导入mergeConfig避免浅拷贝覆盖嵌套配置按 configType 分流用configType DEVELOPMENT / PRODUCTION区分 dev 与 build 环境善用类型TS 项目使用StorybookConfig标注或尝试defineMainCSF Next获得推断了解作用域viteFinal的改动会同时影响 dev server、生产构建与无头工具场景改动面较大需谨慎验证。延伸阅读viteFinal API 参考、Vite 构建器指南、main.js|ts 配置总览。【免费下载链接】storybookStorybook is the industry standard workshop for building, documenting, and testing UI components in isolation项目地址: https://gitcode.com/GitHub_Trending/st/storybook创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
网站建设高端定制企业官网