Vue项目多环境配置实战:从process.env到自动化部署
1. 为什么需要多环境配置?
刚开始接触Vue项目时,我也觉得环境配置是个可有可无的东西。直到有一次,我在本地开发时调用的API地址忘记切换,直接把测试环境的代码发布到了线上,导致用户看到了一堆测试数据。那次事故让我深刻认识到,环境配置不是锦上添花,而是项目开发的必需品。
在真实项目中,我们通常会遇到四种典型环境:
- 开发环境(dev):本地开发调试用,可能需要mock数据或连接开发服务器
- 测试环境(test):QA团队验证功能,需要独立的数据源
- 预发布环境(staging):尽可能模拟生产环境,用于最终验证
- 生产环境(prod):真实线上环境,直接影响终端用户
每个环境的配置差异可能包括:
- API接口地址
- 第三方SDK密钥
- 日志级别
- 功能开关
- 分析统计ID
手动维护这些配置不仅容易出错,还会让代码库充满各种if-else判断。这就是为什么我们需要建立一套规范的环境管理体系。
2. 环境变量的基础实现
2.1 process.env的工作原理
process.env是Node.js环境下的全局变量,它包含了当前进程的所有环境变量信息。在Vue CLI创建的项目中,webpack会在构建时将这些环境变量静态替换到客户端代码中。
这里有个关键点需要注意:只有以VUE_APP_开头的变量才会被webpack打包进客户端代码。这是出于安全考虑,避免意外泄露敏感信息。
// 正确的定义方式
VUE_APP_API_URL=https://api.dev.example.com
// 错误的定义方式(不会被打包)
SECRET_KEY=123456
2.2 .env文件的使用规范
在项目根目录下,我们可以创建多个.env文件来管理不同环境的配置:
.env # 在所有环境中共享的默认值
.env.local # 本地覆盖配置,应该加入.gitignore
.env.development # 开发环境专用
.env.production # 生产环境专用
.env.test # 测试环境专用
文件加载的优先级很有意思:
- .env.local
- .env.[mode]
- .env
这意味着你可以在.env中设置通用配置,在特定环境文件中覆盖个别值。比如:
# .env
VUE_APP_API_VERSION=v1
VUE_APP_LOG_LEVEL=debug
# .env.production
VUE_APP_LOG_LEVEL=error
2.3 实际配置示例
让我们看一个完整的配置案例:
# .env.development
NODE_ENV=development
VUE_APP_BASE_API=https://dev-api.example.com
VUE_APP_CDN_URL=https://dev-cdn.example.com
VUE_APP_GA_ID=UA-XXXXX-1
VUE_APP_DEBUG=true
# .env.production
NODE_ENV=production
VUE_APP_BASE_API=https://api.example.com
VUE_APP_CDN_URL=https://cdn.example.com
VUE_APP_GA_ID=UA-XXXXX-2
VUE_APP_DEBUG=false
在package.json中配置对应的启动命令:
{
"scripts": {
"serve": "vue-cli-service serve --mode development",
"build": "vue-cli-service build --mode production",
"build:stage": "vue-cli-service build --mode staging",
"test": "vue-cli-service test --mode test"
}
}
3. 多环境高级配置技巧
3.1 环境变量智能提示
在TypeScript项目中,我们可以通过声明文件增强环境变量的类型提示。在src目录下创建env.d.ts:
declare namespace NodeJS {
interface ProcessEnv {
readonly NODE_ENV: 'development' | 'production' | 'test'
readonly VUE_APP_TITLE: string
readonly VUE_APP_API_BASE: string
// 添加其他自定义环境变量
}
}
这样在代码中使用process.env时,就能获得自动补全和类型检查,避免拼写错误。
3.2 动态配置方案
有时候我们需要在运行时动态加载配置,而不是在构建时硬编码。这时可以结合public目录下的配置文件:
- 在public目录创建config.json
{
"apiBaseUrl": "/api",
"cdnUrl": "/static"
}
- 在应用启动时加载配置
// src/utils/config.js
let runtimeConfig = {}
export async function loadConfig() {
const response = await fetch('/config.json')
runtimeConfig = await response.json()
}
export function getConfig(key) {
return runtimeConfig[key] || process.env[`VUE_APP_${key}`]
}
这种方案特别适合需要频繁修改配置的场景,比如不同客户部署的定制化版本。
3.3 安全最佳实践
环境变量中经常会包含敏感信息,这里有几个安全建议:
- 永远不要把敏感信息提交到代码仓库
# .gitignore
.env.local
*.env.*.local
- 使用加密工具管理敏感变量
# 安装加密工具
npm install --save-dev dotenv-vault
# 加密.env文件
npx dotenv-vault local encrypt
- 在CI/CD中安全注入变量
# GitHub Actions示例
jobs:
build:
steps:
- uses: actions/checkout@v2
- run: npm install
- run: npm run build
env:
VUE_APP_SECRET: ${{ secrets.API_KEY }}
4. 与CI/CD流程集成
4.1 自动化构建配置
现代前端项目通常会通过CI/CD工具实现自动化构建和部署。以GitHub Actions为例:
name: Build and Deploy
on:
push:
branches: [ main ]
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
env: [production, staging]
steps:
- uses: actions/checkout@v2
- name: Setup Node
uses: actions/setup-node@v2
with:
node-version: '14'
- name: Install dependencies
run: npm install
- name: Build for ${{ matrix.env }}
run: npm run build:${{ matrix.env }}
env:
VUE_APP_VERSION: ${{ github.sha }}
VUE_APP_BUILD_TIME: ${{ steps.get-date.outputs.date }}
- name: Upload artifacts
uses: actions/upload-artifact@v2
with:
name: dist-${{ matrix.env }}
path: dist
4.2 多阶段部署策略
对于企业级项目,建议采用分阶段部署策略:
- 开发阶段:每次push触发自动构建和部署到开发环境
- 测试阶段:合并到test分支时部署到测试环境
- 预发布阶段:打tag时部署到staging环境
- 生产阶段:手动触发生产环境部署
对应的GitHub Workflow配置:
jobs:
deploy:
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Setup Node
uses: actions/setup-node@v2
- name: Install dependencies
run: npm ci
- name: Build production
run: npm run build
env:
VUE_APP_API_URL: ${{ secrets.PROD_API_URL }}
- name: Deploy to Production
uses: JamesIves/github-pages-deploy-action@4.1.5
with:
branch: gh-pages
folder: dist
4.3 环境健康检查
部署完成后,建议添加自动化健康检查:
// src/utils/healthCheck.js
export async function healthCheck() {
try {
const response = await fetch(`${process.env.VUE_APP_API_URL}/health`)
if (!response.ok) throw new Error('Health check failed')
const data = await response.json()
console.log(`Environment: ${process.env.NODE_ENV}`)
console.log(`API Version: ${data.version}`)
return true
} catch (error) {
console.error('Health check error:', error)
return false
}
}
在main.js中调用:
import { healthCheck } from './utils/healthCheck'
healthCheck().then(healthy => {
if (!healthy) {
// 显示环境错误提示
}
})
5. 常见问题与解决方案
5.1 环境变量未生效排查
当环境变量没有按预期生效时,可以按照以下步骤排查:
- 确认文件名是否正确匹配mode参数
- 检查变量名是否以VUE_APP_开头
- 确保文件位于项目根目录
- 重启开发服务器(环境变量在启动时被固化)
- 检查变量名拼写是否正确
- 查看webpack配置是否有覆盖
可以在vue.config.js中添加调试信息:
console.log('Env variables:', process.env)
5.2 跨项目共享配置
在微前端架构中,多个子项目可能需要共享基础配置。这时可以创建共享配置模块:
- 创建config包
packages/
config/
src/
index.js
package.json
- 在index.js中导出通用配置
const sharedConfig = {
appName: 'My App',
apiTimeout: 30000
}
module.exports = {
...sharedConfig,
...process.env
}
- 在各子项目中引用
const config = require('@myorg/config')
5.3 本地开发代理设置
开发时经常需要解决跨域问题,可以在vue.config.js中配置代理:
module.exports = {
devServer: {
proxy: {
'/api': {
target: process.env.VUE_APP_PROXY_TARGET || 'http://localhost:3000',
changeOrigin: true,
pathRewrite: {
'^/api': ''
}
}
}
}
}
对应的.env.development文件:
VUE_APP_PROXY_TARGET=https://dev-api.example.com
6. 现代替代方案探索
6.1 Vite环境变量处理
如果你使用Vite而非webpack,环境变量的处理方式略有不同:
- 变量前缀变为VITE_而非VUE_APP_
- 暴露方式更加直接,无需额外配置
- 支持更灵活的.env文件命名
示例:
# .env
VITE_API_URL=https://api.example.com
# 代码中使用
console.log(import.meta.env.VITE_API_URL)
6.2 动态环境注入
对于需要完全动态配置的场景,可以考虑在Docker容器启动时注入:
FROM nginx:alpine
COPY dist /usr/share/nginx/html
COPY env.sh /docker-entrypoint.d/
RUN chmod +x /docker-entrypoint.d/env.sh
env.sh脚本:
#!/bin/sh
# 生成runtime-config.js
cat > /usr/share/nginx/html/runtime-config.js <<EOF
window.__env__ = {
API_URL: "${API_URL:-https://api.example.com}",
DEBUG: "${DEBUG:-false}"
};
EOF
exec "$@"
6.3 功能开关实现
基于环境变量可以实现功能开关:
// src/features.js
export const features = {
newDashboard: process.env.VUE_APP_FEATURE_DASHBOARD === 'true',
experimentalAPI: process.env.VUE_APP_FEATURE_EXPERIMENTAL_API === 'true'
}
// 使用方式
import { features } from './features'
if (features.newDashboard) {
// 启用新功能
}
这样可以通过环境变量控制功能的开启和关闭,而无需修改代码或重新构建。
更多推荐
所有评论(0)