环境变量与 runtimeConfig
本教程共 50 篇 · 第 35 篇 · 更新于 2026-08-08 · 约 8 分钟阅读
本节目标:能用
runtimeConfig定义公开与私密配置,用.env在部署时覆盖它们,并清楚哪些配置会暴露到浏览器、哪些不会。
写应用时总有些「环境相关」的值:开发用测试库地址、上线用正式库地址;第三方 API 的密钥不能让人看见;前端要用的接口基地址又要能公开。把这些值硬编码进代码既不安全也不灵活。Nuxt 用 runtimeConfig 配合 .env 环境变量解决这件事,是项目从「能跑」到「能上线」的关键一步。
35-1
你可能会想:直接在 nuxt.config.ts 里写个常量不就行了?问题在于——这些值的真正取值往往要到部署时才知道(不同环境不同密钥),而且有些值(比如密钥)绝不能出现在发给浏览器的代码里。runtimeConfig 的巧思是:先在配置里定义「占位和结构」,运行时再用环境变量覆盖;同时它自动区分「能公开给浏览器」和「只能服务端用」两类。
千万不要把密钥直接写进前端代码,也别用 process.env.XXX 在前端代码里直接读——构建时它可能没值,而且容易误把私密值打包进客户端。统一走 runtimeConfig 才是正道。
35-2
在 nuxt.config.ts 的 runtimeConfig 里定义。顶层键是私密的(只有服务端能拿到);放在 public 里的键是公开的(服务端和浏览器都能拿到)。
export default defineNuxtConfig({
runtimeConfig: {
// 私密键:仅服务端可用
apiSecret: '123',
// 公开键:服务端和客户端都能用
public: {
apiBase: '/api',
},
},
})
apiSecret 这种密钥只活在服务器,永远不会进浏览器。public.apiBase 会被打进每个页面的载荷(payload),前端随时能读。Nuxt 会自动生成类型,访问时也有提示。
Note
runtimeConfig的值会被序列化后交给 Nitro,所以不能放函数、Set、Map 这类不可序列化的东西。需要这类逻辑,请放进插件或中间件里写。
35-3
最常见的用法:本地和线上用不同密钥,靠 .env 文件提供。Nuxt CLI 在开发、构建、生成阶段会自动读取项目根目录的 .env。
NUXT_API_SECRET=api_secret_token
NUXT_PUBLIC_API_BASE=https://nuxtjs.org
环境变量的命名规则很关键:必须以 NUXT_ 开头,用下划线 _ 表示层级和大小写分隔。所以 apiSecret 对应 NUXT_API_SECRET,public.apiBase 对应 NUXT_PUBLIC_API_BASE。Nuxt 运行时看到匹配的环境变量,就会自动覆盖对应配置。
export default defineNuxtConfig({
runtimeConfig: {
apiSecret: '', // 被 NUXT_API_SECRET 覆盖
public: {
apiBase: '', // 被 NUXT_PUBLIC_API_BASE 覆盖
},
},
})
Warning在
nuxt.config里把默认值写成「指向另一个名字的环境变量」(比如myVar: process.env.OTHER)只在构建期有效,运行时就会失效。请务必让环境变量名和runtimeConfig的结构对上,用NUXT_前缀那套规则。
NoteNuxt CLI 在 dev/build/generate 时会读
.env;但运行打包后的服务器时,.env不会被自动读取——这时要靠运行环境(云平台面板、Docker、shell)直接提供NUXT_*环境变量。所以上线别只依赖本地.env文件。
35-4
读配置统一用 useRuntimeConfig(),但客户端和服务端拿到的是不同的「视图」:
- 服务端:整个 runtimeConfig 都能读,包括私密键。但它是只读的,避免请求之间串数据。
- 客户端:只有
public和 Nuxt 内部的app部分可见,且对象是响应式、可写的。
<script setup lang="ts">
const config = useRuntimeConfig()
console.log('运行配置:', config)
if (import.meta.server) {
// 只有服务端能拿到私密键
console.log('API 密钥:', config.apiSecret)
}
</script>
<template>
<div>接口基地址:{{ config.public.apiBase }}</div>
</template>
在 Vue 模板里,公开配置还能用更短的 $config.public 直接访问。
Caution安全红线:绝不要把私密键渲染到页面、或塞进
useState共享给前端。一旦config.apiSecret出现在客户端代码里,密钥就泄露了。只在该服务端用的地方(如 server 路由)读它。
35-5
服务端接口是最常需要私密配置的地方,比如带着密钥去调第三方 API:
export default defineEventHandler(async (event) => {
const config = useRuntimeConfig(event)
const repo = await $fetch('https://api.github.com/repos/nuxt/nuxt', {
headers: {
Authorization: `token ${config.apiSecret}`,
},
})
return repo
})
Tip在服务端路由里调用
useRuntimeConfig(event)时,建议把event传进去。这样运行时由环境变量覆盖的值才能正确生效(Nitro 会按请求上下文解析)。不传也能用,但传了更稳妥。
35-6
Nuxt 会根据你的配置自动推断类型,但如果想更严格,可以在 index.d.ts 里手动补全接口:
declare module 'nuxt/schema' {
interface RuntimeConfig {
apiSecret: string
}
interface PublicRuntimeConfig {
apiBase: string
}
}
export {}
写业务代码时就能享受到完整的类型提示和校验。
35-7
容易和 runtimeConfig 搞混的还有 app.config.ts:它放的是「构建时就确定、且公开」的值(如站点标题、主题色),不能用环境变量覆盖,但支持热更新、响应式、非原始类型。一句话区分:
- 需要上线后靠环境变量填的私密/公开令牌 →
runtimeConfig。 - 构建时定死的公共配置(主题、标题) →
app.config。
35-8
这一章掌握了 Nuxt 配置管理的核心:runtimeConfig 里顶层键是私密(仅服务端)、public 下是公开(双端可用);用 NUXT_ 前缀的 .env 在运行时覆盖;前端靠 useRuntimeConfig().public 读,服务端用 useRuntimeConfig(event) 还能拿私密键。牢记安全红线——私密键只在服务端用,别让它溜进浏览器。至此「样式、资源、服务端能力」三大块就讲完了,你已经具备用 Nuxt 写一个带后端接口的小应用的知识基础。
35-7 环境管理的最佳实践
在实际项目中,通常需要管理多个环境:开发、测试、预发布、生产。每个环境的 API 地址、数据库连接、第三方密钥都可能不同。Nuxt 通过 .env 文件和 runtimeConfig 提供了一套完整的环境管理方案。
建议为每个环境创建独立的 .env 文件:.env.development、.env.staging、.env.production。运行构建或开发时,通过 --dotenv 参数指定加载哪个文件。敏感信息(如 API 密钥)只放在 .env 里,不要提交到代码仓库,记得把它们加到 .gitignore。
在 CI/CD 流水线里,环境变量通常由平台提供(如 Vercel 的环境变量设置、GitHub Actions 的 Secrets)。确保这些平台的环境变量名和本地 .env 保持一致,可以避免”本地能跑、部署就挂”的问题。
35-8 配置的安全边界
管理环境变量和运行时配置时,安全是首要考虑。Nuxt 的 runtimeConfig 分两层:顶层字段只在服务端可用(安全),public 子字段会暴露给客户端(不安全)。理解这个区别至关重要。
API 密钥、数据库连接字符串、第三方服务的 Secret 等敏感信息,必须放在 runtimeConfig 的顶层,绝不能放在 public 里。一旦放到 public,这些值会被打包进前端 JavaScript,任何人都能在浏览器里看到。
另一个常见的安全疏忽是把 .env 文件提交到了 Git 仓库。务必在 .gitignore 里添加 .env、.env.local、.env.*.local 等规则。CI/CD 环境里的密钥通过平台的环境变量功能注入,不要依赖 .env 文件。