Storybook 环境变量完全指南:STORYBOOK_ 前缀、.env 文件与浏览器配置实战
2026/9/10 21:32:03 网站建设 项目流程

Storybook 环境变量完全指南:STORYBOOK_ 前缀、.env 文件与浏览器配置实战

【免费下载链接】storybookStorybook is the industry standard workshop for building, documenting, and testing UI components in isolation项目地址: https://gitcode.com/GitHub_Trending/st/storybook

本文围绕 Storybook 官方文档 环境变量指南 及其配套代码片段 storybook-read-environment-variables.md 展开,系统讲解如何在不同“模式”下通过环境变量改变 Storybook 的行为:从命令行动态注入、.env文件静态配置,到在预览代码(process.envimport.meta.env)、自定义<head>/<body>以及 stories 中读取变量,再到用BROWSER/BROWSER_ARGS控制预览浏览器。读完本文,你将掌握一套可复制的环境变量工作流,并能理解其底层实现(Vite 的envPrefix合并逻辑、浏览器打开的源码分支)以便自行排查问题。

核心机制:STORYBOOK_前缀注入

Storybook 规定:只有以STORYBOOK_开头的环境变量才会被注入到浏览器端的预览代码中。无论你使用 Webpack 还是 Vite 构建器,只要提供了带此前缀的变量,它就会分别出现在:

  • Webpack 构建器:process.env
  • Vite 构建器:import.meta.env

以官方文档给出的命令行注入为例:

STORYBOOK_THEME=red STORYBOOK_DATA_KEY=12345 npm run storybook

启动后,这两个变量即可在预览 JavaScript 代码中的任意位置读取:

console.log(process.env.STORYBOOK_THEME); console.log(process.env.STORYBOOK_DATA_KEY);
console.log(import.meta.env.STORYBOOK_THEME); console.log(import.meta.env.STORYBOOK_DATA_KEY);

第一段适用于 Webpack 构建器(如 Angular、Ember、React Webpack5 等框架),第二段适用于 Vite 构建器(如 React Vite、Vue3 Vite、Svelte Vite、Web Components Vite 等)。

为什么是这两个访问入口:Vite 构建器的前缀合并逻辑

如果你好奇import.meta.env.STORYBOOK_THEME为什么能被识别,可以查看 Vite 构建器的核心实现 codegen-modern-iframe-script.ts 与插件 storybook-config-plugin.ts。后者是一个enforce: 'pre'的 Vite 插件,在配置合并阶段做了两件事:

  1. 如果用户自己的 Vite 配置中已经指定了envPrefix,Storybook 会把'STORYBOOK_'合并进去;
  2. 如果用户没有指定envPrefix,Storybook 会默认设置为['VITE_', 'STORYBOOK_'],既保留 Vite 默认的VITE_前缀能力,又保证STORYBOOK_前缀的变量能被import.meta.env暴露出来。

这就是文档中“使用 Vite 时,STORYBOOK_VITE_前缀的变量均可通过import.meta.env访问”的源码级依据。

安全红线:不要把机密信息放进 Storybook

官方文档在开篇就给出了一条重要警告:不要在 Storybook 中存储任何密钥(如私有 API 密钥)或其他敏感信息。原因是环境变量会被内嵌进构建产物中——任何人只要检查静态文件,就能看到这些值。这一点无论对process.env还是import.meta.env都成立,因为它们在构建期就被“硬编码”进了打包结果。

因此,STORYBOOK_前缀变量适合存放非敏感的运行时配置,例如主题色、功能开关、API 基础地址、演示数据键等。

在自定义<head>/<body>中使用占位符替换

除了在 JS 代码中读取,环境变量还可以通过占位符%STORYBOOK_X%的形式注入到自定义的<head>/<body>中。例如,若你通过.env或命令行设置了STORYBOOK_THEME=red,那么在preview-head.htmlpreview-body.html中写%STORYBOOK_THEME%,最终会替换为red

一个典型场景是动态引用样式表地址:

<link rel="stylesheet" href="%STORYBOOK_STYLE_URL%" />

官方文档特别提醒:如果占位符被用作 JS 的属性或值,可能需要手动加上引号,因为替换是纯文本直接插入的。例如href="%STORYBOOK_STYLE_URL%"中的引号需要自己保留,否则替换结果会因缺引号而失效。

使用.env文件管理不同模式

命令行注入适合临时变量;长期稳定的配置更适合放进.env文件。在项目根目录创建一个.env文件:

STORYBOOK_DATA_KEY=12345

之后该变量可以在任何地方访问,包括 stories 内部。官方配套示例 my-component-with-env-variables.md 展示了各框架的完整写法,下面是 React 的 CSF 3 版本:

import type { Meta, StoryObj } from '@storybook/react-vite'; import { MyComponent } from './MyComponent'; const meta = { component: MyComponent, } satisfies Meta<typeof MyComponent>; export default meta; type Story = StoryObj<typeof meta>; export const ExampleStory: Story = { args: { propertyA: process.env.STORYBOOK_DATA_KEY, }, };

如果你使用 Svelte CSF,也可以把变量直接塞进<Story>args

<script module> import { defineMeta } from '@storybook/addon-svelte-csf'; import MyComponent from './MyComponent.svelte'; const { Story } = defineMeta({ component: MyComponent, }); </script> <Story name="ExampleStory" args={{ propertyA: process.env.STORYBOOK_DATA_KEY }} />

按模式拆分:.env.development.env.production

针对不同运行模式,Storybook 还支持按文件名加载专属变量:添加.env.development.env.production,即可在不同模式下应用不同的值。这一机制让你可以在开发模式使用本地调试地址、在生产构建时自动切换到正式地址,而无需改动任何代码。

Vite 构建器:使用import.meta.env读取

官方文档单独为 Vite 用户开辟了一节:Storybook 默认提供的 Vite 构建器不会输出 Node.js 全局对象process.env。因此在使用 Vite 时,访问环境变量(如STORYBOOK_VITE_前缀)必须改用import.meta.env

配套示例 my-component-vite-env-variables.md 给出了同时读取STORYBOOK_VITE_前缀变量的写法(React CSF 3 版本):

import type { Meta, StoryObj } from '@storybook/react-vite'; import { MyComponent } from './MyComponent'; const meta = { component: MyComponent, } satisfies Meta<typeof MyComponent>; export default meta; type Story = StoryObj<typeof meta>; export const ExampleStory: Story = { args: { propertyA: import.meta.env.STORYBOOK_DATA_KEY, propertyB: import.meta.env.VITE_CUSTOM_VAR, }, };

Svelte CSF 版本同理:

<script module> import { defineMeta } from '@storybook/addon-svelte-csf'; import MyComponent from './MyComponent.svelte'; const { Story } = defineMeta({ component: MyComponent, }); </script> <Story name="ExampleStory" args={{ propertyA: import.meta.env.STORYBOOK_DATA_KEY, propertyB: import.meta.env.VITE_CUSTOM_VAR, }} />

构建静态站点:build-storybook时的变量固化

环境变量不仅作用于本地开发,还可以在构建静态 Storybook 时传入:

STORYBOOK_DATA_KEY=12345 npm run build-storybook

此时变量会被硬编码进静态版本中。这意味着发布后的 Storybook 站点也会携带这些值(再次强调:不要放敏感信息)。结合.env.production,这是实现“开发与生产使用不同 API 地址”的标准做法。

通过 Storybook 配置定义变量:main.jsenv字段

除了命令行和.env文件,你还可以在 Storybook 配置文件中扩展定义特定变量(如 API URL)。在.storybook/main.js|ts中添加env字段,其值为一个接收现有配置对象并返回新配置对象的函数:

export default { // Replace your-framework with the framework you are using, e.g. react-vite, nextjs, vue3-vite, etc. framework: '@storybook/your-framework', stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'], /* * 👇 The `config` argument contains all the other existing environment variables. * Either configured in an `.env` file or configured on the command line. */ env: (config) => ({ ...config, EXAMPLE_VAR: 'An environment variable configured in Storybook', }), };

TypeScript 版本使用StorybookConfig类型约束:

// Replace your-framework with the framework you are using, e.g. react-vite, nextjs, 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)'], /* * 👇 The `config` argument contains all the other existing environment variables. * Either configured in an `.env` file or configured on the command line. */ env: (config) => ({ ...config, EXAMPLE_VAR: 'An environment variable configured in Storybook', }), }; export default config;

注意函数参数config中已经包含了.env文件或命令行配置的全部既有变量,通过...config展开即可在保留它们的基础上追加新变量。Storybook 加载后,这些变量就能像.env文件里的变量一样在 stories 中读取。配套示例 my-component-env-var-config.md 演示了读取方式,例如(React CSF 3):

import type { Meta, StoryObj } from '@storybook/react-vite'; import { MyComponent } from './MyComponent'; const meta = { component: MyComponent, } satisfies Meta<typeof MyComponent>; export default meta; type Story = StoryObj<typeof meta>; export const Basic: Story = { args: { exampleProp: process.env.EXAMPLE_VAR, }, };

另外,若项目使用 CSF Next(实验性语法),可改用defineMain包一层,例如 Vue3:

import { defineMain } from '@storybook/vue3-vite/node'; export default defineMain({ framework: '@storybook/vue3-vite', stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'], env: (config) => ({ ...config, EXAMPLE_VAR: 'An environment variable configured in Storybook', }), });

用环境变量选择预览浏览器

Storybook 允许你通过环境变量指定启动时预览 stories 所用的浏览器,既可以在.env文件中设置,也可以直接在storybook启动脚本里临时指定。可用的选项如下表:

浏览器示例
SafariBROWSER="safari"
FirefoxBROWSER="firefox"
ChromiumBROWSER="chromium"

默认情况下,Storybook 启动时会打开一个新的 Chrome 窗口。如果你的机器没有安装 Chrome,请务必设置上述选项之一,或配置好系统默认浏览器。

还可以通过BROWSER_ARGS给浏览器传递额外参数。例如以隐身模式打开 Chrome:

BROWSER="chrome" BROWSER_ARGS="--incognito" npm run storybook

注意:BROWSER_ARGS仅在同时显式设置了BROWSER时才生效

浏览器机制背后的源码实现

上述行为的实现位于 opener.ts 与 open-in-browser.ts。从源码结构可以推断出更完整的规则:

  • BROWSER未设置时走默认Actions.BROWSER分支,由open库按系统默认处理;
  • BROWSER=none时走Actions.NONE,完全阻止打开浏览器(对应open-in-browser.ts中“openBrowser返回false表示有意设置了BROWSER=none”的注释,该行为用于修复 CI 场景下的问题 #24191);
  • BROWSER指向.js/.mjs/.cjs/.ts文件时,Storybook 会用 Node.js 执行该脚本并把 URL 作为参数传入;
  • BROWSER指向.sh脚本时,会尝试用sh执行(Windows PowerShell 上不支持,需要 WSL,否则抛出BrowserEnvError);
  • BROWSER_ARGS会按空格拆分后传给浏览器进程。

这些分支都有对应的单元测试覆盖,见 opener.test.ts,其中包含BROWSER指向 JS/MJS/CJS 文件、shell 脚本、以及BROWSER='google chrome'搭配BROWSER_ARGS='--incognito'等用例。此外,在 macOS 上 Storybook 还会尝试用 AppleScript 复用已打开的 Chromium 系浏览器标签页(支持 Chrome、Edge、Brave、Vivaldi、Chromium 等)。

另外,在 CI 或 Docker 等无头环境中,若浏览器打开失败,可改用--ci标志禁止自动打开浏览器。

故障排查

process变量未被识别

如果你使用的是 Webpack 系框架(例如 Angular + Webpack),在引用STORYBOOK_前缀变量时遇到Can't find variable: process之类的运行时错误,通常是因为一个或多个环境变量缺失或未正确配置。解决办法是:确保它们已通过.env文件配置、通过命令行参数注入,并按照上文“Using Storybook configuration”一节为变量提供默认值。

环境变量不生效

如果你尝试使用框架专属的环境变量(例如VUE_APP_),可能会遇到问题。根本原因在于 Storybook 与你的框架各自有特定的配置,彼此未必能识别对方前缀的变量。此时需要调整框架配置,让框架能识别这些变量。例如 Vite 系框架可以扩展配置文件并开启envPrefix选项(这正是上文 Vite 插件实现所做的事);其他框架通常也需要类似的配置调整。

总结:选择合适的环境变量策略

需求场景推荐方案
临时调试、一次性运行命令行前缀注入:STORYBOOK_X=... npm run storybook
稳定的团队共享配置项目根目录.env文件
开发/生产差异化.env.development.env.production
需要代码内编程式追加变量.storybook/main.js|ts中的env配置函数
静态构建产物携带配置STORYBOOK_X=... npm run build-storybook硬编码
指定/禁用预览浏览器BROWSERBROWSER_ARGS(配合--ci

四条核心原则贯穿始终:只用STORYBOOK_前缀Webpack 用process.env而 Vite 用import.meta.env%STORYBOOK_X%占位符用于 HTML 注入绝不放敏感信息。按此实践,你就能让同一套 Storybook 在不同环境下游刃有余。

【免费下载链接】storybookStorybook is the industry standard workshop for building, documenting, and testing UI components in isolation项目地址: https://gitcode.com/GitHub_Trending/st/storybook

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询