Storybook 中使用 Vite 构建器时通过 import.meta.env 访问环境变量的完整指南
2026/9/8 16:33:09 网站建设 项目流程

Storybook 中使用 Vite 构建器时通过 import.meta.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_前缀的环境变量会注入到预览代码的运行时环境中;当使用 Vite 构建器时,由于 Vite 不会输出process.env这类 Node.js 全局对象,这些变量需要通过import.meta.env来读取。本文基于 Storybook 官方文档的环境变量片段(my-component-vite-env-variables.md,被 Environment variables 的 “With Vite” 小节引用)展开,覆盖从配置环境变量、在 Story 中消费的多种写法(CSF 3 / Svelte CSF / CSF Next),到 Vite 构建器底层如何决定哪些变量能进入客户端代码的完整链路,并给出排障方法。

为什么 Vite 下要用 import.meta.env

Storybook 的环境变量机制是:命令行或.env文件中提供的前缀变量(如STORYBOOK_),会被打包进预览 bundle,在预览 JavaScript 代码中随取随用。在 Webpack 构建器下访问入口是process.env,而在使用 Vite builder 时,process.env这类 Node.js 全局对象不会被输出到产物中,因此官方文档明确建议改用import.meta.env

Out of the box, Storybook provides a Vite builder, which does not output Node.js globals likeprocess.env. To access environment variables in Storybook (e.g.,STORYBOOK_,VITE_), you can useimport.meta.env.

也就是说,在 Vite 体系(react-vite、vue3-vite、svelte-vite、web-components-vite、preact-vite 等)中,import.meta.env.STORYBOOK_DATA_KEYimport.meta.env.VITE_CUSTOM_VAR就是读取环境变量的标准方式。

第一步:如何提供这些环境变量

在读取之前,先确认变量从哪来。官方文档给出三种供给方式:

1. 命令行临时注入——启动时前置环境变量:

STORYBOOK_THEME=red STORYBOOK_DATA_KEY=12345 npm run storybook

2..env文件——在项目根目录添加.env

STORYBOOK_DATA_KEY=12345

3. 按模式区分的文件——可以使用.env.development.env.production为开发态 / 构建态提供不同的值。

安全红线同样重要:环境变量会被直接内联(embed)进构建产物,任何人检查静态文件都能看到值,因此绝不能把私钥、API 密钥等敏感信息放入 Storybook 的环境变量中

第二步:在 Story 中通过 import.meta.env 消费变量

以下是原片段文档继承下来的核心用法:把环境变量作为args传入 Story。以 React(CSF 3,TypeScript)为例:

// Replace your-framework with the framework you are using, e.g. react-vite, nextjs, vue3-vite, etc. import type { Meta, StoryObj } from '@storybook/your-framework'; 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, }, };

同一段逻辑在 JavaScript(CSF 3)下的写法更简洁:

export default { component: 'my-component', }; export const ExampleStory = { args: { propertyA: import.meta.env.STORYBOOK_DATA_KEY, propertyB: import.meta.env.VITE_CUSTOM_VAR, }, };

Svelte 项目既可以用 CSF 3,也可以用 Svelte CSF 的defineMeta

<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, }} />

**CSF Next(实验性 API)**则通过preview.meta/meta.story的工厂形式组织,React 示例:

import preview from '../.storybook/preview'; import { MyComponent } from './MyComponent'; const meta = preview.meta({ component: MyComponent, }); export const ExampleStory = meta.story({ args: { propertyA: import.meta.env.STORYBOOK_DATA_KEY, propertyB: import.meta.env.VITE_CUSTOM_VAR, }, });

Vue 项目的 CSF Next 写法同理,只是组件导入换成.vue文件(import MyComponent from './MyComponent.vue')。

无论哪种框架、哪种 CSF 风格,模式完全一致:import.meta.env.<KEY>出现在 Story 模块顶层,构建时即被静态替换为具体值。这意味着变量在构建时被固化,而不是运行时动态拉取。

底层原理:Vite 构建器如何决定哪些变量进入客户端

结合仓库源码,可以完整还原import.meta.env背后的处理链路。

1. 默认前缀是VITE_STORYBOOK_Vite 构建器内置的 storybook:config-plugin 会在配置阶段合并envPrefix:如果用户在viteFinal里自定义了envPrefix,就在原值基础上追加STORYBOOK_;否则直接使用['VITE_', 'STORYBOOK_']

const mergedEnvPrefix = existingEnvPrefix ? Array.from( new Set([ ...(Array.isArray(existingEnvPrefix) ? existingEnvPrefix : [existingEnvPrefix]), 'STORYBOOK_', ]) ) : ['VITE_', 'STORYBOOK_'];

这一点有对应测试用例佐证:vite-config.test.ts 中“should set default envPrefix when no user envPrefix is set”断言结果envPrefix严格等于['VITE_', 'STORYBOOK_']

2. 环境变量白名单过滤后生成 define 替换规则。运行时插件调用 envs.ts 中的stringifyProcessEnvs,它只做两类放行:命中内置白名单的键(STORYBOOKBASE_URLMODEDEVPRODSSR——即 Vite 自带的import.meta.env默认变量),或以允许的前缀开头(VITE_STORYBOOK_、或用户envPrefix)的键:

const allowedEnvVariables = [ 'STORYBOOK', 'BASE_URL', 'MODE', 'DEV', 'PROD', 'SSR', ]; // 只有白名单值、envPrefix 数组命中的值、或带允许前缀的字符串才会被加入 acc[`import.meta.env.${key}`] = JSON.stringify(value);

放行后的变量被写成import.meta.env.<KEY> => JSON.stringify(value)的 define 映射;同时还会生成import.meta.env整体对象的映射,以支持const { foo } = import.meta.env这种解构写法。所以前面 Story 示例中的import.meta.env.STORYBOOK_DATA_KEY最终是被编译期替换成了字面量字符串。

3. 变量从哪加载:loadEnvs核心侧的 envs.ts 用lazy-universal-dotenv读取.env系列文件,与process.env合并后,只保留匹配/^STORYBOOK_/的键,并附加NODE_ENVNODE_PATHSTORYBOOKPUBLIC_URL等基础变量。注释中还有一个值得注意的细节:dotenv的值会覆盖process.env的同名键——“it seems wrong that dotenv overrides process.env, but that's how it has always worked”,这是历史行为,排障时若发现.env值“赢了”命令行值,根因即在此。

补充能力:head/body 中的 %STORYBOOK_X% 替换

除了 JS 代码内访问,带STORYBOOK_前缀的变量还可以用在自定义的<head>/<body>模板里,占位符%STORYBOOK_X%会被直接替换为对应值(例如STORYBOOK_THEME=red时,%STORYBOOK_THEME%变成red)。其实现见 template.ts:对每个键值对执行string.replace(new RegExp(%${k}%, 'g'), v)

注意:当替换结果被用作 JavaScript 的属性或字符串值时,可能需要自行补上引号,因为值是被“原样插入”的。官方文档给的例子是<link rel="stylesheet" href="%STORYBOOK_STYLE_URL%" />

构建时:build-storybook 会把变量硬编码进产物

build-storybook生成静态 Storybook 时,同样可以传入这些环境变量,它们会被硬编码(hardcode)进静态版本。这与前面源码层面“构建期静态替换”的机制互相印证:产物中不存在运行时读取环境变量的能力,只有替换后的常量。因此不同环境(开发 / 生产 / CI)需要不同行为时,正确做法是分别提供.env.development.env.production,或在构建命令中显式传入,而不是指望运行时变化。

排障:框架专属前缀的变量读不到

如果你的变量使用了框架专属前缀(例如 Vue 的VUE_APP_),Storybook 的 Vite 构建器默认不会放行它们——因为默认前缀只有VITE_STORYBOOK_。官方文档的排障建议是扩展 Vite 配置、显式配置envPrefix选项,让构建器识别你的前缀。对应源码行为也很直白:storybook-config-plugin.ts 会把用户配置的envPrefix(字符串或数组)与STORYBOOK_合并去重,所以自定义前缀可以平滑叠加,而STORYBOOK_前缀永远生效。

另一类常见误用是期望import.meta.env能读到未加任何允许前缀的变量——按 envs.ts 的白名单逻辑,这类键在 define 阶段就被过滤掉了,产物中自然取不到值。

小结

  • 供给STORYBOOK_前缀变量可通过命令行、.env.env.development/.env.production三种方式提供;VITE_前缀沿用 Vite 自身机制。
  • 读取:Vite 构建器下统一用import.meta.env.<KEY>,与 CSF 3 / Svelte CSF / CSF Next 均兼容;Webpack 构建器下对应入口是process.env
  • 原理:默认envPrefix['VITE_', 'STORYBOOK_'](见 storybook-config-plugin.ts),构建期由 stringifyProcessEnvs 做白名单过滤并静态替换,值被硬编码进产物。
  • 边界:模板 HTML 中可用%STORYBOOK_X%占位符替换;敏感信息严禁放入环境变量;框架专属前缀需自行扩展envPrefix配置。

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

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

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

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

立即咨询