欢迎光临茂名市分类吧
详情描述

Vite + Vue3 跨域环境变量配置全过程

一、环境变量配置

1. 创建环境变量文件

在项目根目录创建以下文件:

.env                # 所有环境通用(最低优先级)
.env.local          # 本地环境通用,git忽略
.env.development    # 开发环境
.env.production     # 生产环境
.env.staging        # 预发布环境
2. 环境变量示例

.env.development (开发环境):

# API 基础地址
VITE_API_BASE_URL = /api

# 完整 API 地址(用于其他配置)
VITE_API_FULL_URL = http://localhost:3000

# 其他变量
VITE_APP_TITLE = My App (Development)

.env.production (生产环境):

VITE_API_BASE_URL = /api
VITE_API_FULL_URL = https://api.example.com
VITE_APP_TITLE = My App
3. 使用环境变量

在代码中通过 import.meta.env 访问:

const apiBaseUrl = import.meta.env.VITE_API_BASE_URL
const appTitle = import.meta.env.VITE_APP_TITLE

二、跨域代理配置

1. vite.config.js 配置
import { defineConfig, loadEnv } from 'vite'
import vue from '@vitejs/plugin-vue'
import { resolve } from 'path'

export default defineConfig(({ mode }) => {
  // 加载环境变量
  const env = loadEnv(mode, process.cwd())

  return {
    plugins: [vue()],

    // 服务器配置
    server: {
      port: 5173, // 开发服务器端口
      host: true, // 监听所有地址
      open: true, // 自动打开浏览器

      // 代理配置
      proxy: {
        // 代理规则1:以 /api 开头的请求
        '/api': {
          target: env.VITE_API_FULL_URL, // 从环境变量读取
          changeOrigin: true, // 修改请求头中的host值
          rewrite: (path) => path.replace(/^\/api/, '') // 重写路径
        },

        // 代理规则2:多个API端点
        '/auth': {
          target: 'http://auth.example.com',
          changeOrigin: true,
          rewrite: (path) => path.replace(/^\/auth/, '/api/auth')
        },

        // WebSocket 代理
        '/socket': {
          target: 'ws://localhost:3001',
          ws: true,
          changeOrigin: true
        }
      }
    },

    // 构建配置
    build: {
      outDir: 'dist',
      sourcemap: mode !== 'production', // 生产环境关闭sourcemap
      // 环境变量定义
      define: {
        __APP_ENV__: JSON.stringify(env.APP_ENV)
      }
    },

    // 路径别名
    resolve: {
      alias: {
        '@': resolve(__dirname, 'src')
      }
    }
  }
})

三、TypeScript 支持

1. 创建 env.d.ts 文件

src 目录下创建 env.d.ts

/// <reference types="vite/client" />

interface ImportMetaEnv {
  // 基础配置
  readonly VITE_APP_TITLE: string
  readonly VITE_API_BASE_URL: string
  readonly VITE_API_FULL_URL: string

  // 业务相关变量
  readonly VITE_UPLOAD_URL: string
  readonly VITE_CDN_URL: string

  // 第三方配置
  readonly VITE_GA_ID: string
  readonly VITE_SENTRY_DSN: string
}

interface ImportMeta {
  readonly env: ImportMetaEnv
}

四、封装 API 请求

1. 创建 src/utils/request.ts
import axios, { type AxiosRequestConfig, type AxiosResponse } from 'axios'

// 创建 axios 实例
const service = axios.create({
  baseURL: import.meta.env.VITE_API_BASE_URL,
  timeout: 10000,
  headers: {
    'Content-Type': 'application/json'
  }
})

// 请求拦截器
service.interceptors.request.use(
  (config) => {
    // 添加 token
    const token = localStorage.getItem('token')
    if (token) {
      config.headers.Authorization = `Bearer ${token}`
    }

    // 开发环境打印请求信息
    if (import.meta.env.DEV) {
      console.log(`📤 ${config.method?.toUpperCase()} ${config.url}`, config.params || config.data)
    }

    return config
  },
  (error) => {
    return Promise.reject(error)
  }
)

// 响应拦截器
service.interceptors.response.use(
  (response: AxiosResponse) => {
    // 开发环境打印响应信息
    if (import.meta.env.DEV) {
      console.log(`📥 ${response.status} ${response.config.url}`, response.data)
    }

    return response.data
  },
  (error) => {
    // 统一错误处理
    if (error.response) {
      switch (error.response.status) {
        case 401:
          // token 过期处理
          break
        case 403:
          // 权限不足
          break
        case 500:
          // 服务器错误
          break
      }
    }
    return Promise.reject(error)
  }
)

export default service
2. 创建 API 模块
// src/api/user.ts
import request from '@/utils/request'

export const userAPI = {
  // 登录
  login(data: { username: string; password: string }) {
    return request.post('/auth/login', data)
  },

  // 获取用户信息
  getUserInfo() {
    return request.get('/user/info')
  },

  // 上传文件
  uploadFile(data: FormData) {
    return request.post('/upload', data, {
      headers: {
        'Content-Type': 'multipart/form-data'
      }
    })
  }
}

五、环境变量验证

1. 创建验证脚本
// scripts/validate-env.js
const fs = require('fs')
const path = require('path')

// 必需的环境变量
const requiredEnvVars = [
  'VITE_API_BASE_URL',
  'VITE_API_FULL_URL'
]

function validateEnvFile(filePath) {
  if (!fs.existsSync(filePath)) {
    return
  }

  console.log(`检查 ${filePath}`)
  const content = fs.readFileSync(filePath, 'utf-8')
  const lines = content.split('\n')

  lines.forEach(line => {
    if (line.trim() && !line.startsWith('#')) {
      const [key] = line.split('=')
      if (!key) return

      if (requiredEnvVars.includes(key.trim())) {
        console.log(`✓ ${key.trim()}`)
      }
    }
  })
}

// 检查所有环境文件
const envFiles = [
  '.env.development',
  '.env.production',
  '.env.staging'
]

envFiles.forEach(file => {
  validateEnvFile(path.join(__dirname, '..', file))
})
2. package.json 添加脚本
{
  "scripts": {
    "dev": "vite",
    "dev:local": "vite --mode development",
    "dev:test": "vite --mode staging",
    "build": "vite build",
    "build:prod": "vite build --mode production",
    "build:staging": "vite build --mode staging",
    "preview": "vite preview",
    "validate-env": "node scripts/validate-env.js",
    "lint": "eslint . --ext .vue,.js,.ts"
  }
}

六、部署配置

1. Docker 配置
# Dockerfile
FROM node:18-alpine as builder

WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

FROM nginx:alpine
COPY --from=builder /app/dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
2. Nginx 配置
# nginx.conf
server {
    listen 80;
    server_name localhost;

    # 开启 gzip
    gzip on;
    gzip_min_length 1k;
    gzip_comp_level 9;
    gzip_types text/plain text/css text/javascript application/json application/javascript application/xml+rss;
    gzip_vary on;

    # 静态资源
    location / {
        root /usr/share/nginx/html;
        index index.html;
        try_files $uri $uri/ /index.html;
    }

    # API 代理
    location /api/ {
        proxy_pass http://backend:3000/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    # 静态文件缓存
    location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
    }
}

七、使用示例

1. 组件中使用
<template>
  <div>
    <h1>{{ title }}</h1>
    <button @click="fetchData">获取数据</button>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { userAPI } from '@/api/user'

const title = import.meta.env.VITE_APP_TITLE
const apiBaseUrl = import.meta.env.VITE_API_BASE_URL

const fetchData = async () => {
  try {
    const data = await userAPI.getUserInfo()
    console.log('数据:', data)
  } catch (error) {
    console.error('请求失败:', error)
  }
}
</script>
2. 开发时使用不同环境
# 开发环境(默认)
npm run dev

# 指定开发环境
npm run dev --mode development

# 测试环境
npm run dev --mode staging

# 生产环境构建
npm run build:prod

# 预发布环境构建
npm run build:staging

# 预览生产构建
npm run preview

八、注意事项

环境变量命名:必须以 VITE_ 开头才能在客户端访问 敏感信息:不要在前端环境变量中存储敏感信息 类型安全:及时更新 env.d.ts 类型定义 代理配置:开发环境使用代理,生产环境使用 Nginx 等服务器配置 缓存问题:修改环境变量后需要重启开发服务器

这样配置后,你的 Vite + Vue3 项目就具备了完整的跨域代理和环境变量管理能力。

相关帖子
茂名市120救护车跑长途出租,长途医疗转运车出租电话
茂名市120救护车跑长途出租,长途医疗转运车出租电话
茂名市危险化学品经营许可证办理|公司执照代办服务,收费透明
茂名市危险化学品经营许可证办理|公司执照代办服务,收费透明
“她死了,但她的香水还在”:法国版《俄罗斯女子学院》用“气味线索”串联悬疑,比血迹更勾人
“她死了,但她的香水还在”:法国版《俄罗斯女子学院》用“气味线索”串联悬疑,比血迹更勾人
神话与现实的交错:狮子在各国传说中象征意义的对比研究
神话与现实的交错:狮子在各国传说中象征意义的对比研究
茂名市120救护车跨省运送病人,120救护车一次多少钱
茂名市120救护车跨省运送病人,120救护车一次多少钱
呼和浩特市长途救护车出租公司,长途120救护车护送病人返乡
呼和浩特市长途救护车出租公司,长途120救护车护送病人返乡
黄冈市企业网站制作设计|手机app开发,提供一站式建站服务
黄冈市企业网站制作设计|手机app开发,提供一站式建站服务
福州市120长途救护车接送病人出院,120救护车怎么叫
福州市120长途救护车接送病人出院,120救护车怎么叫
一文详解Nginx日志的查找与分析技巧
一文详解Nginx日志的查找与分析技巧
张家口市企业获客助手#网站优化推广公司,多年专业建站经验
张家口市企业获客助手#网站优化推广公司,多年专业建站经验
常德市食品经营许可证代办服务-营业执照注册代办,24小时在线,欢迎电话咨询
常德市食品经营许可证代办服务-营业执照注册代办,24小时在线,欢迎电话咨询
株洲市殡葬服务车出租-丧葬服务租车,骨灰落葬
株洲市殡葬服务车出租-丧葬服务租车,骨灰落葬
工资增长指导线的发布,对2026年人才招聘市场有哪些潜在影响?
工资增长指导线的发布,对2026年人才招聘市场有哪些潜在影响?
2026年自由职业者或灵活就业人员申请岗位培训补贴的具体资格与操作步骤是什么?
2026年自由职业者或灵活就业人员申请岗位培训补贴的具体资格与操作步骤是什么?
如果遗失了孩子的出生医学证明,如何通过官方渠道查询到原始编号?
如果遗失了孩子的出生医学证明,如何通过官方渠道查询到原始编号?
永州市个体工商户注销代办电话|公司注册服务电话,无需本人到场,全程代办
永州市个体工商户注销代办电话|公司注册服务电话,无需本人到场,全程代办
遵义市病人转院租120救护车,租急救车护送病人返乡
遵义市病人转院租120救护车,租急救车护送病人返乡
韶关市网站建设推广|AI数字人直播带货,多年专业建站经验
韶关市网站建设推广|AI数字人直播带货,多年专业建站经验
合肥市公司地址变更办理-装修公司注册,不成功不收费,全程代办
合肥市公司地址变更办理-装修公司注册,不成功不收费,全程代办