当前位置:首页 > 文章列表 > 文章 > 前端 > Vite 环境变量为什么不能在运行时直接修改

Vite 环境变量为什么不能在运行时直接修改

来源:17golang原创 2026-10-14 14:56:37 0浏览 收藏

如果你在部署后修改了服务器上的 .env,却发现浏览器里的接口地址完全没变,通常不是 Vite 读取失败,而是把构建期配置误当成了运行时配置。Vite 会在开发服务器启动或生产构建阶段读取环境变量,并把 import.meta.env 中可用的值静态替换进客户端代码;已经生成的 JavaScript 不会在浏览器运行时重新读取服务器文件。

官方地址:https://vite.dev/guide/env-and-mode.html

固定在构建产物里的值继续使用 import.meta.env;需要每次部署后都能切换的接口地址、租户标识或开关,应放在构建产物之外,由页面启动时读取。
  • 构建期值:适合版本标识、编译开关和随环境重新构建的 API 地址。
  • 运行时值:适合同一份静态资源部署到多个环境后再决定的配置。
  • 安全边界:VITE_ 变量会进入客户端代码,不能存放密钥。

先判断:你改的是构建输入,还是浏览器配置

我在排查这类问题时,先把发布链路拆成两段:Vite 运行在 Node.js 环境中,负责读取环境文件并生成静态资源;浏览器只负责加载已经生成的 HTML、JavaScript 和 CSS。两段之间的交界处就是构建产物。浏览器没有义务、也没有通道去重新解析部署服务器上的 .env.production。

因此,下面这种写法表达的是“构建时选定一个值”,不是“页面每次打开都从服务器取值”:

const apiBaseUrl = import.meta.env.VITE_API_BASE_URL

// 这个值在 Vite 启动或构建时注入,页面运行中不会自动回读 .env。
export async function loadUser() {
  const response = await fetch(`${apiBaseUrl}/user`)
  // 保留 HTTP 错误,让调用方决定如何展示失败状态。
  if (!response.ok) throw new Error(`请求失败:${response.status}`)
  return response.json()
}

开发时修改环境文件通常还需要重启开发服务器;生产环境则必须重新构建并重新部署,新的值才会进入新的 bundle。

Vite 环境文件、import.meta.env 与浏览器 bundle 的构建边界静态说明图
图1:构建期配置边界说明图,查看环境文件如何进入客户端产物。

为什么 import.meta.env 看起来像常量

Vite 官方文档把 import.meta.env 描述为一组在构建时静态替换的常量。客户端默认只暴露带有 VITE_ 前缀的自定义变量,而且暴露后的值都是字符串。这个设计让打包器可以做裁剪,也让前端代码保持简单,但代价是配置值和构建结果绑定在一起。

例如 .env.production 中写入 VITE_API_BASE_URL=https://api.example.com,构建后代码拿到的是这个字符串的产物。之后你把服务器文件改成另一个地址,除非重新执行构建,否则原 bundle 仍然携带旧值。

模式文件也属于同一个构建期边界。vite build 默认使用 production 模式;如果使用 vite build --mode staging,Vite 会按 staging 模式加载对应的环境文件。模式选择发生在构建命令中,不是页面打开后由用户切换。

const mode = import.meta.env.MODE
const isProduction = import.meta.env.PROD

// 这些字段描述当前构建模式,适合参与编译期分支或显示版本信息。
export const buildInfo = {
  mode,
  isProduction,
}

还要注意,VITE_ 只是“允许进入客户端”的前缀,不是安全存储机制。API 密钥、数据库密码和签名私钥都不应该放在这里;它们一旦进入 bundle,就可以被访问页面的人看到。

需要运行时切换时,配置要搬到启动边界之外

如果目标是“一份构建产物部署到测试、预发布和生产,再由部署动作决定接口地址”,就不要强行修改 import.meta.env。更稳妥的做法是让部署系统替换一个独立的 config.js,页面启动时先加载它,再让业务代码读取全局配置。

// public/config.js:部署时只替换这个文件,不重新构建业务 bundle。
window.__APP_CONFIG__ = {
  API_BASE_URL: "https://api.example.com"
}
// src/config.js:统一读取运行时配置,避免业务代码到处访问 window。
export function getRuntimeConfig() {
  const config = window.__APP_CONFIG__
  // 缺少配置时尽早失败,避免请求拼出错误地址。
  if (!config?.API_BASE_URL) throw new Error("缺少 API_BASE_URL")
  return config
}

生产部署时可以把 config.js 做成模板,由容器启动脚本、Web 服务器模板变量或服务端渲染入口写入实际地址。这个方案的核心不是某一种文件名,而是把“可变配置”放在编译产物之外,并明确加载顺序与缺失时的失败方式。

部署文件、config.js、window.__APP_CONFIG__ 与应用代码的运行时配置边界静态说明图
图2:运行时配置边界说明图,查看部署后可替换配置与应用读取位置。

三个容易误判的边界

第一,修改了文件但没有重启。开发服务器会在启动阶段加载环境文件,先重启再判断是否生效。生产 bundle 已经生成后,则要重新构建。

第二,把 NODE_ENV 当成 mode。Vite 文档明确区分二者:NODE_ENV 描述 Node 环境,--mode 决定 Vite 读取哪组模式文件。不要只改其中一个,就推断另一个也变了。

第三,把“能在前端读取”当成“可以保密”。所有进入 import.meta.env 的客户端值都应按公开信息处理。真正的密钥应留在后端,再由后端完成需要权限的操作。

常见问题

部署后只改 .env,为什么页面还是旧地址?

因为页面加载的是已经构建好的 JavaScript。重新构建并部署,或把该地址迁移到构建产物之外的运行时配置文件。

所有环境变量都能通过 import.meta.env 读取吗?

默认只有内置变量和带 VITE_ 前缀的变量会暴露给客户端。未加前缀的变量不会直接出现在客户端代码中;自定义前缀也可以通过 Vite 配置调整,但仍然不等于保密。

运行时配置能不能直接修改 import.meta.env?

不建议这样做。它属于 Vite 构建期提供的环境接口,不是设计给浏览器动态写入的可变对象。需要运行时变化时,建立独立的配置读取层更清楚,也更容易在缺失时给出明确错误。

判断标准可以压缩成一句话:发布前就确定的值放进 import.meta.env,发布后还要改变的值放到独立运行时配置中;任何会被浏览器读取的值,都不能当作秘密保存。

版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
Vite 依赖预构建缓存失效怎样定位Vite 依赖预构建缓存失效怎样定位
上一篇
Vite 依赖预构建缓存失效怎样定位
TypeScript noUncheckedIndexedAccess 开启后的数组读取处理方案
下一篇
TypeScript noUncheckedIndexedAccess 开启后的数组读取处理方案
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    500次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    485次学习
查看更多
AI推荐
  • PubMedQA数据集详解:生物医学问答基准、功能与应用指南
    PubMedQA
    深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
    471次使用
  • H2O EvalGPT:开源LLM大模型评估与排行榜工具
    H2O EvalGPT
    H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
    530次使用
  • LMArena是什么?伯克利AI模型评估平台使用指南与功能解析
    LMArena
    LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
    550次使用
  • 斯坦福HELM:大语言模型Holistic Evaluation整体评估框架详解
    HELM
    深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
    500次使用
  • MMBench详解:多模态大模型基准测试、功能特点与使用指南
    MMBench
    MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
    318次使用