AI.Demo/DEPLOY.md

11 KiB
Raw Blame History

AI 英语学习辅助平台 — 线上部署操作流程

项目概述

  • 项目名称AI 英语学习辅助平台
  • 技术栈Vue 3 + Vite + Vue RouterHistory 模式)
  • 构建产物纯静态文件HTML / CSS / JS可部署到任意静态托管服务

一、部署前准备

1.1 环境要求

工具 版本要求
Node.js >= 18.x推荐 20.x LTS
npm >= 9.x
node -v
npm -v

1.2 安装依赖

cd AI_Demo
npm install

二、关键配置说明

2.1 API 配置(必须在部署前确认)

项目所有 API 密钥集中在 src/config/index.js,部署前请确认以下配置项均已填写正确:

配置项 说明
GRS_API_KEY GRS AI 接口密钥(作文批改 / 试题分析)
DOUBAO_APP_ID 豆包语音 App ID
DOUBAO_ACCESS_TOKEN 豆包语音访问令牌
DOUBAO_RESOURCE_ID 豆包 TTS 资源 ID
DOUBAO_ASR_RESOURCE_ID 豆包 ASR 资源 ID
ARK_API_KEY 火山引擎 Ark 大模型密钥
ARK_MODEL Ark 模型名称(如 doubao-pro-4k

2.2 跨域响应头要求(重要)

项目使用了 @ffmpeg/ffmpegWebAssembly需要服务器返回以下响应头否则视频讲解功能将无法运行

Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: require-corp

各部署平台的配置方式见下方对应章节。

2.3 API 代理配置(重要)

项目在开发环境通过 Vite 代理转发以下 API 请求,生产环境必须在服务器/网关层配置对应的反向代理

前端请求路径前缀 代理目标 用途
/tts-api https://openspeech.bytedance.com 豆包 TTS 语音合成
/ark-api https://ark.cn-beijing.volces.com 火山引擎 Ark 大模型
/dashscope-api https://dashscope.aliyuncs.com 阿里云百炼
/asr-ws wss://openspeech.bytedance.com 豆包 ASR WebSocket

ASR WebSocket 特殊说明/asr-ws 代理需要在代理层注入以下鉴权 Header浏览器原生 WebSocket 不支持自定义 Header

  • X-Api-App-Key
  • X-Api-Access-Key
  • X-Api-Resource-Id
  • X-Api-Connect-Id(每次连接随机 UUID

三、构建生产包

npm run build

构建完成后,产物位于 dist/ 目录,包含:

dist/
├── index.html
├── favicon.svg
└── assets/
    ├── *.js
    └── *.css

可在本地预览构建结果:

npm run preview

四、部署方案

方案 ANginx 部署(推荐,自有服务器)

4.A.1 上传文件

dist/ 目录内容上传到服务器,例如 /var/www/ai-demo/

scp -r dist/* user@your-server:/var/www/ai-demo/

4.A.2 Nginx 配置

创建或修改 Nginx 站点配置文件(如 /etc/nginx/sites-available/ai-demo.conf

server {
    listen 80;
    server_name your-domain.com;  # 替换为你的域名或 IP

    root /var/www/ai-demo;
    index index.html;

    # 跨域响应头FFmpeg WASM 必需)
    add_header Cross-Origin-Opener-Policy "same-origin" always;
    add_header Cross-Origin-Embedder-Policy "require-corp" always;

    # Vue Router History 模式:所有路由回退到 index.html
    location / {
        try_files $uri $uri/ /index.html;
    }

    # 代理:豆包 TTS
    location /tts-api/ {
        proxy_pass https://openspeech.bytedance.com/;
        proxy_ssl_server_name on;
        proxy_set_header Host openspeech.bytedance.com;
    }

    # 代理:火山引擎 Ark
    location /ark-api/ {
        proxy_pass https://ark.cn-beijing.volces.com/;
        proxy_ssl_server_name on;
        proxy_set_header Host ark.cn-beijing.volces.com;
    }

    # 代理:阿里云百炼
    location /dashscope-api/ {
        proxy_pass https://dashscope.aliyuncs.com/;
        proxy_ssl_server_name on;
        proxy_set_header Host dashscope.aliyuncs.com;
    }

    # 代理:豆包 ASR WebSocket需注入鉴权 Header
    location /asr-ws/ {
        proxy_pass https://openspeech.bytedance.com/;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host openspeech.bytedance.com;
        proxy_ssl_server_name on;
        # 注入豆包 ASR 鉴权 Header替换为实际值
        proxy_set_header X-Api-App-Key "YOUR_DOUBAO_APP_ID";
        proxy_set_header X-Api-Access-Key "YOUR_DOUBAO_ACCESS_TOKEN";
        proxy_set_header X-Api-Resource-Id "volc.bigasr.sauc.duration";
    }

    # 静态资源缓存
    location /assets/ {
        expires 1y;
        add_header Cache-Control "public, immutable";
        add_header Cross-Origin-Opener-Policy "same-origin" always;
        add_header Cross-Origin-Embedder-Policy "require-corp" always;
    }
}

4.A.3 启用配置并重启 Nginx

# 启用站点Ubuntu/Debian
ln -s /etc/nginx/sites-available/ai-demo.conf /etc/nginx/sites-enabled/

# 检查配置语法
nginx -t

# 重载 Nginx
systemctl reload nginx

4.A.4 配置 HTTPS推荐

# 使用 Certbot 申请免费 SSL 证书
apt install certbot python3-certbot-nginx
certbot --nginx -d your-domain.com

方案 BNode.js + Express 静态服务器

适用于需要在 Node.js 环境中自定义响应头的场景。

4.B.1 安装依赖

npm install express http-proxy-middleware

4.B.2 创建服务器文件 server.js

import express from 'express'
import { createProxyMiddleware } from 'http-proxy-middleware'
import { fileURLToPath } from 'url'
import path from 'path'
import crypto from 'crypto'

const __dirname = path.dirname(fileURLToPath(import.meta.url))
const app = express()
const PORT = process.env.PORT || 3000

// 全局注入 COOP/COEP 响应头FFmpeg WASM 必需)
app.use((req, res, next) => {
  res.setHeader('Cross-Origin-Opener-Policy', 'same-origin')
  res.setHeader('Cross-Origin-Embedder-Policy', 'require-corp')
  next()
})

// API 代理
app.use('/tts-api', createProxyMiddleware({
  target: 'https://openspeech.bytedance.com',
  changeOrigin: true,
  pathRewrite: { '^/tts-api': '' }
}))

app.use('/ark-api', createProxyMiddleware({
  target: 'https://ark.cn-beijing.volces.com',
  changeOrigin: true,
  pathRewrite: { '^/ark-api': '' }
}))

app.use('/dashscope-api', createProxyMiddleware({
  target: 'https://dashscope.aliyuncs.com',
  changeOrigin: true,
  pathRewrite: { '^/dashscope-api': '' }
}))

app.use('/asr-ws', createProxyMiddleware({
  target: 'wss://openspeech.bytedance.com',
  changeOrigin: true,
  ws: true,
  pathRewrite: { '^/asr-ws': '' },
  on: {
    proxyReqWs: (proxyReq) => {
      proxyReq.setHeader('X-Api-App-Key', process.env.DOUBAO_APP_ID)
      proxyReq.setHeader('X-Api-Access-Key', process.env.DOUBAO_ACCESS_TOKEN)
      proxyReq.setHeader('X-Api-Resource-Id', 'volc.bigasr.sauc.duration')
      proxyReq.setHeader('X-Api-Connect-Id', crypto.randomUUID())
    }
  }
}))

// 静态文件服务
app.use(express.static(path.join(__dirname, 'dist')))

// Vue Router History 模式回退
app.get('*', (req, res) => {
  res.sendFile(path.join(__dirname, 'dist', 'index.html'))
})

app.listen(PORT, () => {
  console.log(`Server running at http://localhost:${PORT}`)
})

4.B.3 启动服务

DOUBAO_APP_ID=xxx DOUBAO_ACCESS_TOKEN=xxx node server.js

方案 CEdgeOne Pages / Vercel / Netlify纯静态托管

注意:此类平台不支持服务端代理/tts-api/ark-api/dashscope-api/asr-ws 等接口将因跨域或缺少鉴权 Header 而失败。
建议仅用于演示或配合独立后端服务使用。

部署步骤(以 Vercel 为例)

  1. 将项目推送到 GitHub
  2. 在 Vercel 控制台导入仓库
  3. 构建命令:npm run build,输出目录:dist
  4. 创建 vercel.json 配置 History 模式路由回退和响应头:
{
  "rewrites": [{ "source": "/(.*)", "destination": "/index.html" }],
  "headers": [
    {
      "source": "/(.*)",
      "headers": [
        { "key": "Cross-Origin-Opener-Policy", "value": "same-origin" },
        { "key": "Cross-Origin-Embedder-Policy", "value": "require-corp" }
      ]
    }
  ]
}

五、部署后验证清单

验证项 检查方法
页面正常加载 访问首页,确认 7 个功能卡片显示正常
路由刷新不 404 直接访问 /pronunciation/speaking 等子路由
COOP/COEP 响应头 浏览器 DevTools → Network → 查看 index.html 响应头
TTS 语音合成 进入发音练习页,测试语音播放
ASR 语音识别 进入口语对话页,测试麦克风录音识别
作文批改 进入作文批改页,提交一段英文作文
视频讲解FFmpeg 进入视频讲解页,上传视频文件测试
HTTPS 证书 确认浏览器地址栏显示锁形图标

六、常见问题排查

Q1视频讲解页面报错 SharedArrayBuffer is not defined

原因:服务器未返回 Cross-Origin-Opener-Policy: same-originCross-Origin-Embedder-Policy: require-corp 响应头。
解决:参考第二节 2.2,在 Nginx 或 Node.js 服务器中添加对应响应头。

Q2刷新页面出现 404

原因Vue Router 使用 History 模式,服务器未配置路由回退。
解决Nginx 添加 try_files $uri $uri/ /index.html;Node.js 添加通配路由返回 index.html

Q3API 请求跨域报错CORS

原因:生产环境未配置反向代理,浏览器直接请求第三方 API 被跨域拦截。
解决:参考第二节 2.3,在 Nginx 或 Node.js 中配置对应代理规则。

Q4ASR 语音识别 WebSocket 连接失败

原因:代理未注入豆包 ASR 鉴权 Header或 WebSocket 升级配置缺失。
解决:确认 Nginx 配置中包含 proxy_set_header Upgrade $http_upgrade; 及三个 X-Api-* Header。

Q5构建时内存不足

原因:项目包含 FFmpeg WASM构建产物较大。
解决

# 增大 Node.js 内存限制
NODE_OPTIONS=--max-old-space-size=4096 npm run build

七、目录结构参考

AI_Demo/
├── dist/                    # 构建产物(部署此目录)
├── src/
│   ├── config/index.js      # API 密钥配置(部署前确认)
│   ├── router/index.js      # 路由定义
│   └── views/               # 页面组件
├── vite.config.js           # 开发代理配置(生产环境需在服务器复现)
├── package.json
└── DEPLOY.md                # 本文档