Vue3+Vite 部署阿里云 OSS 避坑指南:搞定 API 接口 404 与动态环境注入

🚀 Vue3+Vite 部署阿里云 OSS (Object Storage Service, 对象存储服务) 避坑指南:搞定 API (Application Programming Interface, 应用程序编程接口) 接口 404 与动态环境注入

在前后端分离的架构中,我们通常采用 “前端托管 OSS (Object Storage Service, 对象存储服务) + 后端部署 K8s (Kubernetes, 容器编排系统)” 的黄金组合。这种方案成本极低、访问速度极快。

但在将 Vue3 项目推送到阿里云 OSS (Object Storage Service, 对象存储服务) 后,我遇到了一个经典的 API (Application Programming Interface, 应用程序编程接口) 请求 404 问题。今天就来复盘一下这个从“本地跑得通”到“线上火葬场”的排查与解决过程。🛠️

📊 核心问题与解决方案速查表

问题现象根本原因解决方案涉及工具/技术
线上 API (Application Programming Interface, 应用程序编程接口) 报 404前端请求发给了 OSS (Object Storage Service, 对象存储服务) 域名,而非后端网关 IP (Internet Protocol, 互联网协议)注入真实网关 IP (Internet Protocol, 互联网协议) 到生产环境配置Shell 脚本, .env.production
Vite 代理失效server.proxy 仅在开发模式生效,构建后失效修改 Axios 配置,优先读取环境变量Vite, Axios
手动部署繁琐每次需手动修改配置并拖拽上传编写一键自动化部署脚本CLI (Command Line Interface, 命令行界面), ossutil
路由不匹配前端路径带 /api 但网关只认 /auth脚本注入时去除 /api 后缀,或修改网关 StripPrefixShell, Spring Cloud Gateway

😱 问题现场:本地完美,上线 404

  • 本地环境 (npm run dev):接口访问正常,请求地址是 http://localhost:3000/api/auth/...,通过 Vite 的 server.proxy 转发到后端,一切丝滑。
  • 线上环境 (OSS (Object Storage Service, 对象存储服务)):执行 build 并上传 OSS (Object Storage Service, 对象存储服务) 后,访问域名 http://mdt.center,浏览器 Network 面板却一片爆红!🚨

请求地址变成了:

http://mdt.center/api/auth/admin/captcha404 Not Found

奇怪了,我的后端网关明明在 47.108.xx.xx,为什么浏览器还在傻傻地请求 OSS (Object Storage Service, 对象存储服务) 的域名?OSS (Object Storage Service, 对象存储服务) 里当然没有 API (Application Programming Interface, 应用程序编程接口) 接口啊!


🔍 根因分析:Vite 代理的“谎言”

经过排查,发现了两个认知误区:

  1. Vite 的 server.proxy 仅在开发模式生效:一旦执行 npm run build,生成的代码就是纯粹的 HTML (HyperText Markup Language, 超文本标记语言) / JS (JavaScript, 脚本语言) 静态文件,Vite 服务不存在了,代理配置自然也就失效了。
  2. Axios 配置写死:检查代码发现,Axios 的 baseURL 被硬编码成了 /api
    // ❌ 致命错误:写死了相对路径
    const service = axios.create({ baseURL: '/api' })
    
    在生产环境,/api 会被浏览器解析为 当前域名 + /api,也就是去请求 OSS (Object Storage Service, 对象存储服务),导致 404。

🎯 破局思路:我们需要在打包构建(Build)的那一刻,把真实的后端网关 IP (Internet Protocol, 互联网协议) 注入到代码里,并让 Axios 读取它。


✅ 解决方案:DevOps (Development and Operations, 开发运维一体化) 脚本 + 代码改造

第一步:编写部署脚本,强制注入环境变量 💉

为了避免手动修改 .env.production 文件容易出错,我们编写一个 Shell 脚本 (deploy-web.sh)。

它在 npm run build 之前,暴力覆盖 生产环境配置文件,把网关 IP (Internet Protocol, 互联网协议) 写入 VITE_APP_BASE_API

deploy-web.sh 内容如下:

#!/bin/bash

# ================= 🔧 配置区域 =================
# 1. 你的 OSS (Object Storage Service, 对象存储服务) Bucket 名称
BUCKET_NAME="hx-health-cloud-test"

# 2. 你的后端网关公网 IP (Internet Protocol, 互联网协议) 
# ⚠️ 注意:不加 /api 后缀,直接指向网关 IP (Internet Protocol, 互联网协议)
BACKEND_API="http://xxxx"

# 3. 构建输出目录
DIST_DIR="dist"
# ==============================================

# 颜色定义
GREEN='\033[0;32m'
RED='\033[0;31m'
YELLOW='\033[1;33m'
NC='\033[0m'

echo -e "${YELLOW}🚀 开始前端自动化部署流程...${NC}"

# 0. 检查 ossutil 是否安装
if ! command -v ossutil &> /dev/null; then
    echo -e "${RED}❌ 未检测到 ossutil 工具!${NC}"
    echo "请先执行 brew install ossutil 安装,并运行 ossutil config 配置账号。"
    exit 1
fi

# 1. 安装依赖
echo -e "${YELLOW}📦 [1/3] 检查依赖...${NC}"
# npm install --registry=https://registry.npmmirror.com

# 2. 构建项目
echo -e "${YELLOW}🏗️  [2/3] 开始构建项目 (npm run build)...${NC}"
echo "👉 注入后端 API (Application Programming Interface, 应用程序编程接口) 地址: $BACKEND_API"

# 🔥【核心差异】强烈建议用这种方式!
# 直接生成 .env.production 文件,确保 Vite 绝对能读到这个变量
cat > .env.production <<EOF
NODE_ENV=production
VITE_APP_BASE_API=$BACKEND_API
VUE_APP_BASE_API=$BACKEND_API
REACT_APP_BASE_API=$BACKEND_API
EOF

echo -e "${GREEN}✅ 环境变量文件 .env.production 已生成${NC}"

# 🚑【容错处理】临时修改 package.json 跳过 TS (TypeScript, 类型脚本语言) 类型检查
sed -i '' 's/"vue-tsc --noEmit && vite build"/"vite build"/g' package.json 2>/dev/null || sed -i 's/"vue-tsc --noEmit && vite build"/"vite build"/g' package.json

npm run build

if [ $? -ne 0 ]; then
    echo -e "${RED}❌ 构建失败,请检查代码错误!${NC}"
    exit 1
fi
echo -e "${GREEN}✅ 构建成功!${NC}"

# 3. 上传到 OSS (Object Storage Service, 对象存储服务)
echo -e "${YELLOW}☁️  [3/3] 正在上传到阿里云 OSS (Object Storage Service, 对象存储服务) ($BUCKET_NAME)...${NC}"

# -r: 递归上传文件夹
# -f: 强制覆盖
# --meta: 设置 Cache-Control:no-cache 确保 index.html 不被浏览器缓存,发版即生效
ossutil cp -r -f $DIST_DIR/ oss://$BUCKET_NAME/ \
--include "*" \
--meta "Cache-Control:no-cache" 

if [ $? -ne 0 ]; then
    echo -e "${RED}❌ 上传失败,请检查 ossutil 配置或网络!${NC}"
    exit 1
fi

echo -e "${GREEN}✅ 上传成功!${NC}"
echo -e "--------------------------------------------------"
echo -e "🎉 网站已发布,请访问:"
# 这里输出你的自定义域名
echo -e "${GREEN}http://mdt.center${NC}"
echo -e "--------------------------------------------------"

第二步:改造 Axios,读取环境变量 🧬

脚本注入了变量,代码得去“读”才行。修改 src/utils/request.ts

import axios from 'axios'

// 创建 axios 实例
const service = axios.create({
  // ✅【核心修改】优先读取注入的环境变量,读不到再回退到 /api (本地开发用)
  baseURL: import.meta.env.VITE_APP_BASE_API || '/api',
  
  timeout: 15000,
  headers: { 'Content-Type': 'application/json;charset=UTF-8' }
})

// ... 拦截器逻辑保持不变

🎉 最终效果

运行脚本 ./deploy-web.sh 后,再次刷新线上页面。

打开 Chrome (Chrome Web Browser, 谷歌浏览器) 开发者工具 -> Network,发现请求变了:

  • Request URL (Uniform Resource Locator, 统一资源定位符): http://47.108.xx.xx/auth/admin/captcha
  • Status Code: 200 OK 🟢

完美!

  1. 浏览器不再请求 OSS (Object Storage Service, 对象存储服务) 域名,而是直接请求后端网关 IP (Internet Protocol, 互联网协议)。
  2. 路径里去掉了 /api,正好匹配网关的 Path=/auth/** 路由规则。
  3. 验证码图片顺利加载!

📊 流程与架构图解

1. 自动化部署流程 (Mermaid Flowchart)

环境变量注入
BACKEND_API = http://47.108.x.x
.env.production
Vite 构建过程
开始部署 deploy-web.sh
生成 .env.production 文件
执行 npm run build
生成 dist 静态资源
使用 ossutil 上传
阿里云 OSS (Object Storage Service, 对象存储服务)

2. 浏览器请求流转 (Mermaid Sequence Diagram)

浏览器 (User)OSS (Object Storage Service, 对象存储服务)后端网关 (Gateway)认证服务 (Auth Service)阶段一:获取静态资源GET /index.html1返回 HTML (HyperText Markup Language, 超文本标记语言) / JS (JavaScript, 脚本语言)2JS (JavaScript, 脚本语言) 读取到BASE_URL = http://47.108.x.x阶段二:API (Application Programming Interface, 应用程序编程接口) 请求GET http://47.108.x.x/auth/captcha3直连网关 IP (Internet Protocol, 互联网协议)不经过 OSS (Object Storage Service, 对象存储服务)转发请求 /auth/captcha4返回验证码图片5返回 200 OK6浏览器 (User)OSS (Object Storage Service, 对象存储服务)后端网关 (Gateway)认证服务 (Auth Service)

3. 部署状态流转 (Mermaid State Diagram)

启动脚本
检查 ossutil
ossutil cp 成功
写入 .env.production
生成 dist 目录
环境检查
配置生成
代码构建
可选
ViteBuild
TSCheck
资源上传
发布完成

4. 前端网络模块类图 (Mermaid Class Diagram)

生成
注入配置
发起调用
DeployScript
+String BACKEND_API
+generateEnvFile()
+runBuild()
+uploadToOSS()
ViteEnv
+String VITE_APP_BASE_API
+String NODE_ENV
AxiosInstance
+String baseURL
+int timeout
+request()
BrowserRequest
+String url
+String method

5. 部署实体关系图 (Mermaid ER Diagram)

DEVELOPERDEPLOY_SCRIPTstringapi_target47.108.x.xstringbuild_cmdnpm run buildOSS_TOOLSTATIC_FILESstringtypeHTML/JS/CSSstringcache_controlno-cacheOSS_BUCKETstringnamehx-health-cloud-teststringaclpublic-readexecutescallsuploadsstored_in

🧠 知识点思维导图

  • Vue3 + OSS (Object Storage Service, 对象存储服务) 部署实战

    • 核心痛点
      • 本地开发正常 (proxy 生效)
      • 线上访问 404 (请求发往 OSS (Object Storage Service, 对象存储服务) 域名)
      • 手动部署繁琐 (Build + Upload)
    • 根因分析
      • Vite server.proxy 仅在 Dev (Development, 开发) 模式有效
      • Axios baseURL 写死为 /api
      • 浏览器将相对路径解析为当前 OSS (Object Storage Service, 对象存储服务) 域名
    • 解决方案
      • DevOps (Development and Operations, 开发运维一体化) 脚本
        • 工具: ossutil (阿里云 CLI (Command Line Interface, 命令行界面))
        • 动作: 动态生成 .env.production
        • 注入: VITE_APP_BASE_API = 网关IP
      • 代码改造
        • 文件: request.ts
        • 逻辑: baseURL = import.meta.env... || '/api'
    • 关键收益
      • 自动化: 一键部署 (30秒)
      • 灵活性: IP (Internet Protocol, 互联网协议) 变动只需改脚本
      • 高可用: 动静分离 (OSS (Object Storage Service, 对象存储服务) + ACK (Alibaba Cloud Container Service for Kubernetes, 阿里云容器服务 Kubernetes 版))
  • Vue3 + OSS (Object Storage Service, 对象存储服务) 部署实战

    • 核心痛点
      • 本地开发正常 (proxy 生效)
      • 线上访问 404 (请求发往 OSS (Object Storage Service, 对象存储服务) 域名)
      • 手动部署繁琐 (Build + Upload)
    • 根因分析
      • Vite server.proxy 仅在 Dev (Development, 开发) 模式有效
      • Axios baseURL 写死为 /api
      • 浏览器将相对路径解析为当前 OSS (Object Storage Service, 对象存储服务) 域名
    • 解决方案
      • DevOps (Development and Operations, 开发运维一体化) 脚本
        • 工具: ossutil (阿里云 CLI (Command Line Interface, 命令行界面))
        • 动作: 动态生成 .env.production
        • 注入: VITE_APP_BASE_API = 网关IP
      • 代码改造
        • 文件: request.ts
        • 逻辑: baseURL = import.meta.env... || '/api'
    • 关键收益
      • 自动化: 一键部署 (30秒)
      • 灵活性: IP (Internet Protocol, 互联网协议) 变动只需改脚本
      • 高可用: 动静分离 (OSS (Object Storage Service, 对象存储服务) + ACK (Alibaba Cloud Container Service for Kubernetes, 阿里云容器服务 Kubernetes 版))

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值