首页 / WXT 浏览器扩展框架教程 / 环境变量:.env 与内置变量

WXT 浏览器扩展框架教程

环境变量:.env 与内置变量

本教程共 45 篇 · 第 27 篇 · 更新于 2026-08-13 · 约 4 分钟阅读

WXT环境变量dotenv.envimport.meta.env内置变量配置

本节目标:学会用 .env 文件管理环境变量,认识 WXT 的内置变量,并掌握在清单里引用环境变量的正确姿势。

环境变量(environment variables)用来存放「随环境变化的值」:API 地址、接口密钥、功能开关。WXT 完全复用 Vite 的 dotenv 机制,学一次,到处用。

环境变量从哪里来

在项目根目录创建 dotenv 文件,里面写 KEY=value 即可。WXT 支持下面这些文件,按需创建:

.env
.env.local
.env.[mode]
.env.[mode].local
.env.[browser]
.env.[browser].local
.env.[mode].[browser]
.env.[mode].[browser].local

其中 [mode] 是构建模式(§26),[browser] 是目标浏览器。比如 .env.production 只在生产构建生效,.env.firefox 只在构建 Firefox 版本时生效。文件名带 .local 的用于本机私有配置,一般写进 .gitignore 不提交。

文件一多,同名变量就可能撞车。优先级遵循 Vite 的约定:已经存在于进程里的环境变量最高,不会被覆盖;带模式后缀的文件优先于不带后缀的;带 .local 的优先于不带 .local 的。简单记——越具体越优先,同名的值取优先级高的一方。

前缀规则:WXT_ 或 VITE_

文件里的变量不是全部都能在代码里用。按照 Vite 的约定,只有以 WXT_VITE_ 开头的变量才会暴露给运行时:

# .env
WXT_API_KEY=your-secret-key
await fetch(`/some-api?apiKey=${import.meta.env.WXT_API_KEY}`);
Tip

不带前缀的变量不会出现在 import.meta.env 里,但它依然存在于进程环境中,配置类文件(比如 wxt.config.ts)可以用 process.env 读取。区分好这两种场景即可。

另外记住:dotenv 文件里的值一律是字符串。需要布尔、数字等类型时自己转换,§26 里 app.config.ts 的写法就是干这个的。

WXT 的内置变量

除了你自己定义的变量,WXT 还根据当前命令注入一组内置变量:

用法类型说明
import.meta.env.MANIFEST_VERSION2 | 3目标清单版本
import.meta.env.BROWSERstring目标浏览器
import.meta.env.CHROMEboolean等价于 BROWSER === "chrome"
import.meta.env.FIREFOXboolean等价于 BROWSER === "firefox"
import.meta.env.SAFARIboolean等价于 BROWSER === "safari"
import.meta.env.EDGEboolean等价于 BROWSER === "edge"
import.meta.env.IS_CHROMEboolean等价于 BROWSER === "chrome"(测试环境也会注入,见 §36)
import.meta.env.OPERAboolean等价于 BROWSER === "opera"

设置 targetBrowsers 配置项后,BROWSER 的类型会收窄成 "chrome" | "firefox" 这样的字面量联合,写代码时能拿到补全和校验。

Vite 自带的变量也能用:MODE(当前模式)、PROD(生产构建时为 true)、DEV(与 PROD 相反)。另外两个 Vite 变量在 WXT 里没什么用:BASE_URL 请改用 browser.runtime.getURLSSR 永远为 false

在清单里引用环境变量

清单里的字段经常需要环境变量,比如 OAuth 的 client_id。此时必须用函数语法

export default defineConfig({
  modules: ['@wxt-dev/module-vue'],
  manifest: () => ({
    oauth2: {
      client_id: import.meta.env.WXT_APP_CLIENT_ID,
    },
  }),
});

原因在于加载顺序:WXT 要等配置文件加载完,才能把 .env 文件读进进程。如果 manifest 写成对象字面量,求值发生在 .env 加载之前,变量自然是空的;写成函数,创建清单对象的时机被推迟到 .env 加载之后。

还有一个细节:配置文件里没有 Vite 的运行时变量,比如 import.meta.env.DEV 在这里是未定义的。想判断开发模式,用函数参数 mode

export default defineConfig({
  manifest: ({ mode }) => {
    const isDev = mode === 'development';
    console.log('Is development mode:', isDev);
    // ...
  },
});

一份 .env.example 模板

真实项目的习惯是提交一份 .env.example 作为变量清单,让别人照葫芦画瓢。mkext 的模板长这样:

# Better Auth backend. Point this at your deployed backend in prod.
VITE_AUTH_URL="http://localhost:3000"
# Public Google Chrome Extension OAuth client ID.
VITE_GOOGLE_EXTENSION_CLIENT_ID=""
# Ahrefs free Domain Rating API key. This is bundled into the extension build.
VITE_AHREFS_API_KEY=""

注意最后一条注释:以 WXT_VITE_ 开头的变量都会打包进扩展产物,等于公开(WXT_ 前缀并不会「只留在构建期」,官方文档里就有在运行时代码用 WXT_API_KEY 的示例)。所以真正的密钥不要放进任何带前缀的变量——构建期才用的配置走 process.env(不进产物,见前面 TIP),运行时确实需要的公开数据(比如 API 地址)才用 WXT_/VITE_ 前缀,并接受它被公开的事实。

Warning

WXT_VITE_ 开头的变量都会进入产物代码,任何用户都能在扩展包里翻到。不要往里面放真正的服务端密钥。

小结

  • WXT_ / VITE_ 前缀的变量进 import.meta.env,不带前缀的走 process.env(只读不打包)。
  • 带前缀的变量都会进产物,密钥一律别放。
  • manifest 里引用环境变量必须用函数语法(manifest: () => ({...}))。