1. 为什么 Vue 项目需要多环境变量配置
刚接触 Vue 项目的同学,大概率都遇到过这种场景:本地开发时接口地址是http://localhost:8080/api,测试环境是https://test.xxx.com/api,正式环境又是另一个域名。如果每次打包上线前都手动改一遍 axios 的 baseURL,改漏一处就是线上事故。
Vue 环境变量配置要解决的核心问题就一个:同一份代码,通过不同命令启动或打包,自动读取不同的接口地址和配置项。它适合所有用 Vue CLI 或 Vite 搭建的项目,尤其是需要区分开发、测试、生产三套环境的团队协作场景。
我试过最原始的做法——在代码里写死一个if (location.hostname === 'localhost')来判断环境,结果测试环境部署到内网域名后直接失效。后来改用.env文件配合package.json脚本,才算彻底理顺。这篇文章会从package.json的 scripts 配置讲起,到.env文件命名规则,再到 axios 封装里读取变量,最后给出npm run切换环境后的验证步骤,每一步都能直接复制到你的项目里跑通。
需要说明的是,Vue CLI 和 Vite 对环境变量的处理规则略有差异,下面会分别标注。如果你用的是 Vue CLI 4/5,VUE_APP_前缀是硬性要求;Vite 则用VITE_前缀。搞混前缀是新手最常见的坑,后面排障章节会专门讲。
2. 前置准备:TaoToken 接入与项目环境确认
在动手改配置之前,先确认两件事:一是你的 Vue 项目能正常npm run serve启动,二是如果你打算把接口请求接到大模型能力上,需要先拿到一个可用的 API Key。这里以 TaoToken 为例说明接入方式,它的接口地址是https://taotoken.net/api,兼容常见的 OpenAI 风格调用格式,适合在 Vue 项目里做对话类功能。
第一步,打开控制台创建密钥。访问https://taotoken.net/console?utm_source=taotoken_aicg_blog_end&utm_content=console&utm_campaign=rewrite,登录后在 API Keys 页面新建一个 Key,复制保存好,这个 Key 只会完整显示一次。
第二步,如果你要长期在项目里做编码辅助或 Agent 类功能,可以了解下 Coding Plan,地址是https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_content=coding-plan&utm_campaign=rewrite,它更适合持续性的开发场景。只是想先验证模型能不能通,用模型对话页面https://taotoken.net/chat?utm_source=taotoken_aicg_blog_end&utm_content=chat&utm_campaign=rewrite发一条消息即可。
第三步,把 Key 写进环境变量文件,而不是硬编码在 JS 里。这正是本篇要讲的核心——.env.development里放开发用的 Key,.env.production里放正式 Key,代码里统一用process.env.VUE_APP_XXX读取。这样即使代码提交到仓库,敏感信息也不会跟着泄露(当然正式项目建议.env.local并加入.gitignore)。
项目侧的准备:确认package.json里已有vue-cli-service或vite依赖,src目录下有一个封装好的 axios 实例文件,比如src/utils/request.js。没有的话,先npm install axios装一个。
3. 可复制配置:package.json 脚本与 .env 文件
3.1 改造 package.json 的 scripts
打开项目根目录的package.json,找到scripts字段。默认通常只有serve和build,我们要加上测试环境的打包命令,通过--mode参数指定模式名。
{ "scripts": { "serve": "vue-cli-service serve --open", "test": "vue-cli-service build --mode testing", "build": "vue-cli-service build --mode production" } }这里三个命令对应三种模式:serve默认走development,test显式指定testing,build显式指定production。注意--mode后面的名字要和后面创建的.env文件名后缀完全一致,写错一个字母就会读不到变量。
如果你用的是 Vite,命令换成vite build --mode testing即可,逻辑一样。
3.2 创建三个 .env 文件
在项目根目录(和package.json同级)新建以下文件。Vue CLI 的规则是:只有VUE_APP_开头的变量才会被注入到客户端代码中,NODE_ENV和BASE_URL是两个默认存在的变量。
.env.development:
NODE_ENV=development VUE_APP_BASE_API=/api VUE_APP_TITLE=本地开发.env.testing:
NODE_ENV=production VUE_APP_BASE_API=https://test.taotoken.net/api VUE_APP_TITLE=测试环境.env.production:
NODE_ENV=production VUE_APP_BASE_API=https://taotoken.net/api VUE_APP_TITLE=正式环境有个细节容易踩坑:.env.testing里NODE_ENV我写的是production,因为测试环境打包出来的产物是要部署到服务器上跑的,需要走生产构建优化。如果你希望测试环境保留 source map 方便排查,可以改成development,但那样打包体积会大很多。这个取舍看团队习惯。
3.3 封装 baseURL 判断逻辑
在src/utils下新建baseURL.js,把环境判断集中在这里,axios 封装文件只负责导入使用。
// src/utils/baseURL.js let baseURL = ''; if (process.env.NODE_ENV === 'development') { // 开发环境走代理,解决跨域 baseURL = process.env.VUE_APP_BASE_API || '/api'; } else if (process.env.NODE_ENV === 'production') { // 正式和测试环境都走这里,具体地址由 .env 文件决定 baseURL = process.env.VUE_APP_BASE_API; } else { baseURL = process.env.VUE_APP_BASE_API; } export default baseURL;更简洁的写法其实一行就够:export default process.env.VUE_APP_BASE_API。因为每个.env文件里已经写好了对应环境的地址,不需要在 JS 里再判断一遍。上面这种写法适合需要根据NODE_ENV做额外逻辑(比如开发环境强制走代理)的场景。
3.4 在 axios 封装中接入
打开你的 axios 封装文件,导入 baseURL 并替换掉写死的地址。
// src/utils/request.js import axios from 'axios'; import baseURL from './baseURL'; const service = axios.create({ baseURL: baseURL, timeout: 10000 }); service.interceptors.request.use( config => { // 可以在这里统一加 token return config; }, error => Promise.reject(error) ); export default service;到这里配置就完成了。核心链路是:npm run命令 →--mode指定模式 → 加载对应.env文件 → 变量注入process.env→ axios 读取baseURL。
4. 验证请求:切换环境后 axios 是否读到正确变量
配置写完不能只看代码,要实际跑一遍确认。下面给出三种命令的验证方法。
先验证开发环境。终端执行npm run serve,项目启动后打开浏览器控制台,在任意组件里打印一下:
console.log('当前环境:', process.env.NODE_ENV); console.log('接口地址:', process.env.VUE_APP_BASE_API);开发环境下应该输出development和/api。此时在 Network 面板发一个请求,Request URL 应该是http://localhost:8080/api/xxx,说明代理生效。
再验证测试环境。执行npm run test,打包完成后进入dist目录,用npx serve dist起一个静态服务(直接双击index.html会因为相对路径问题白屏,这是常见现象)。打开页面后看控制台,VUE_APP_BASE_API应该输出https://test.taotoken.net/api。
最后验证正式环境。执行npm run build,同样起静态服务查看,变量值应为https://taotoken.net/api。
如果要在代码里更直观地看到环境差异,可以在App.vue的mounted里加一行:
mounted() { document.title = process.env.VUE_APP_TITLE || 'Vue App'; }这样切换命令后,浏览器标签页标题会跟着变,一眼就能确认环境加载对不对。
5. 本篇常见错误排查
5.1 变量读出来是 undefined
最常见的原因就是前缀写错。Vue CLI 只认VUE_APP_开头,你写APP_BASE_API或BASE_API都不会被注入。Vite 则只认VITE_开头。检查.env文件里的变量名,以及代码里process.env.后面跟的名字是否完全一致,大小写敏感。
5.2 改了 .env 文件但没生效
环境变量是在构建时注入的,不是运行时读取。改完.env文件必须重启npm run serve,热更新不会重新加载环境变量。打包命令同理,要重新执行一次npm run build。
5.3 npm run test 报 mode 找不到
检查package.json里--mode testing的 testing 和文件名.env.testing是否完全对应。另外注意test这个命令名如果和项目里已有的测试命令冲突,可以改成build:test之类。
5.4 打包后 index.html 直接打开白屏
这是相对路径问题,不是环境变量的锅。在vue.config.js里设置publicPath: './',或者用静态服务器打开。Vue CLI 默认publicPath是/,直接双击打开时资源路径会指向盘符根目录,自然加载不到。
5.5 敏感 Key 被提交到仓库
.env.production如果包含真实 Key,务必加入.gitignore,或者改用.env.production.local(Vue CLI 会优先加载.local后缀的文件且默认被 git 忽略)。团队协作时只提交.env.production的模板,真实值由部署环境注入。
6. 接入文档与后续操作入口
环境变量配好之后,axios 的 baseURL 就能跟着命令自动切换了。如果你要把请求真正接到大模型接口上,下一步是拿到 API Key 并写进对应环境的.env文件。API Keys 管理页面在https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_content=api-keys&utm_campaign=rewrite,创建后复制到.env.development的VUE_APP_API_KEY变量里(记得加VUE_APP_前缀)。
具体的请求参数格式、鉴权头写法、流式返回处理,可以参考接入文档https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_content=doc&utm_campaign=rewrite,里面有完整的 curl 和 JS 示例,对照着改 axios 封装即可。接口基础地址统一用https://taotoken.net/api,不要带多余路径。
如果你在 Vue 项目里做的是长期编码辅助功能,比如自动补全、代码审查这类需要持续调用的场景,Coding Plan 的额度模型会比按次调用更划算,入口在https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_content=coding-plan&utm_campaign=rewrite。只是想快速验证某个模型返回是否符合预期,直接用模型对话页面发一条消息最快,地址是https://taotoken.net/chat?utm_source=taotoken_aicg_blog_end&utm_content=chat&utm_campaign=rewrite。
最后提醒一个实操细节:.env文件里的值不要加引号,VUE_APP_BASE_API=/api这样写就行,加了引号会把引号也当成值的一部分传给 axios,导致请求地址变成"/api"/xxx这种奇怪的样子。这个坑我在两个项目里都踩过,排查半天才发现是引号的问题。