Storybook 中使用 Vite 构建器时通过 import.meta.env 访问环境变量的完整指南
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.envStorybook 的环境变量机制是命令行或.env文件中提供的前缀变量如STORYBOOK_会被打包进预览 bundle在预览 JavaScript 代码中随取随用。在 Webpack 构建器下访问入口是process.env而在使用 Vite builder 时process.env这类 Node.js 全局对象不会被输出到产物中因此官方文档明确建议改用import.meta.envOut 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_KEY与import.meta.env.VITE_CUSTOM_VAR就是读取环境变量的标准方式。第一步如何提供这些环境变量在读取之前先确认变量从哪来。官方文档给出三种供给方式1. 命令行临时注入——启动时前置环境变量STORYBOOK_THEMEred STORYBOOK_DATA_KEY12345 npm run storybook2..env文件——在项目根目录添加.envSTORYBOOK_DATA_KEY123453. 按模式区分的文件——可以使用.env.development和.env.production为开发态 / 构建态提供不同的值。安全红线同样重要环境变量会被直接内联embed进构建产物任何人检查静态文件都能看到值因此绝不能把私钥、API 密钥等敏感信息放入 Storybook 的环境变量中。第二步在 Story 中通过 import.meta.env 消费变量以下是原片段文档继承下来的核心用法把环境变量作为args传入 Story。以 ReactCSF 3TypeScript为例// 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 Metatypeof MyComponent; export default meta; type Story StoryObjtypeof meta; export const ExampleStory: Story { args: { propertyA: import.meta.env.STORYBOOK_DATA_KEY, propertyB: import.meta.env.VITE_CUSTOM_VAR, }, };同一段逻辑在 JavaScriptCSF 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 的defineMetascript module import { defineMeta } from storybook/addon-svelte-csf; import MyComponent from ./MyComponent.svelte; const { Story } defineMeta({ component: MyComponent, }); /script Story nameExampleStory 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它只做两类放行命中内置白名单的键STORYBOOK、BASE_URL、MODE、DEV、PROD、SSR——即 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_ENV、NODE_PATH、STORYBOOK、PUBLIC_URL等基础变量。注释中还有一个值得注意的细节dotenv的值会覆盖process.env的同名键——“it seems wrong that dotenv overrides process.env, but thats how it has always worked”这是历史行为排障时若发现.env值“赢了”命令行值根因即在此。补充能力head/body 中的 %STORYBOOK_X% 替换除了 JS 代码内访问带STORYBOOK_前缀的变量还可以用在自定义的head/body模板里占位符%STORYBOOK_X%会被直接替换为对应值例如STORYBOOK_THEMEred时%STORYBOOK_THEME%变成red。其实现见 template.ts对每个键值对执行string.replace(new RegExp(%${k}%, g), v)。注意当替换结果被用作 JavaScript 的属性或字符串值时可能需要自行补上引号因为值是被“原样插入”的。官方文档给的例子是link relstylesheet 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),仅供参考