Browse Source

docs: 新增 Web 部署 workflow 和 Nginx 配置文档,修正 MQTT URL 配置

- 创建 build-web-deployment.yml workflow,使用 h5_for_webserver.build.js 构建
- 修正 h5_for_webserver.build.js 中的 MQTT URL 为相对路径 /mqtt
- 使用 Nginx 代理模式,API 和 MQTT URL 均为空或相对路径
- 添加完整的 Nginx 配置文档,包含 MQTT WebSocket 代理配置
- 提供 HTTP 和 HTTPS 配置示例、故障排查指南

技术要点:
- MQTT URL 从 ws://localhost:8083/mqtt 改为 /mqtt,避免生产环境连接失败
- 浏览器会自动将相对路径转换为 ws://domain/mqtt 或 wss://domain/mqtt
- nginx 根据路径规则代理到实际的 MQTT broker 服务

改动文件:
- .build/h5_for_webserver.build.js (修改 MQTT URL 配置)
- .github/workflows/build-web-deployment.yml (新增)
- docs/实现/Nginx-Web部署代理配置.md (新增)
dengdx 1 day ago
parent
commit
546cddab01

+ 2 - 2
.build/h5_for_webserver.build.js

@@ -5,7 +5,7 @@ const path = require('path');
 const fs = require('fs-extra');
 
 const TARO_API_URL = ''; //
-const TARO_MQTT_URL = 'ws://localhost:8083/mqtt';
+const TARO_MQTT_URL = '/mqtt';  // 使用相对路径,由 nginx 代理转发
 const rootDir = path.join(__dirname, '..');          // 项目根目录
 
 
@@ -46,4 +46,4 @@ try {
 } catch (err) {
     console.error('Failed to execute npm run pkg:', err.message);
     process.exit(1);
-}
+}

+ 63 - 0
.github/workflows/build-web-deployment.yml

@@ -0,0 +1,63 @@
+name: CI 构建 Web 部署版本(Nginx 代理模式)
+
+on:
+  push:
+    branches:
+      - master
+    paths:
+      - 'src/**'
+      - 'config/**'
+      - '.github/workflows/build-web-deployment.yml'
+  repository_dispatch:
+    types:
+      - webhook_trigger_web
+  workflow_dispatch:  # 支持手动触发
+
+# 并发控制:自动取消旧的运行
+concurrency:
+  group: build-web-deployment-${{ github.ref }}
+  cancel-in-progress: true
+
+jobs:
+  build-h5-web:
+    runs-on: [win-h5-only]
+    steps:
+      - name: 检出代码
+        uses: actions/checkout@v4
+
+      - name: 设置 Node.js 环境
+        uses: actions/setup-node@v4
+        with:
+          node-version: '20'
+
+      - name: 智能安装依赖(跨平台)
+        run: node .build/smart-install.js
+
+      - name: 测试 SSH 连接
+        env:
+          DEPLOY_KEY: ${{ secrets.DEPLOY_KEY }}
+          DEPLOY_HOST: ${{ secrets.DEPLOY_HOST }}
+          DEPLOY_USER: ${{ secrets.DEPLOY_USER }}
+          DEPLOY_PATH: ${{ secrets.WEB_DEPLOY_PATH }}
+        run: node .build/deploy-to-server.js --test
+
+      - name: 构建 H5 (Web 部署 - Nginx 代理模式)
+        shell: powershell
+        env:
+          GH_TOKEN: ${{ secrets.GH_TOKEN }}
+        run: |
+          Write-Host "🌐 Web 部署模式 (Nginx 代理)"
+          Write-Host "   使用 h5_for_webserver.build.js 构建脚本"
+          Write-Host "   API URL: 空 (前端自行构建,nginx根据路径转发)"
+          Write-Host ""
+          Write-Host "当前操作系统平台: Windows"
+          Write-Host "当前CPU架构: $env:PROCESSOR_ARCHITECTURE"
+          node .build/h5_for_webserver.build.js
+
+      - name: 部署到服务器
+        env:
+          DEPLOY_KEY: ${{ secrets.DEPLOY_KEY }}
+          DEPLOY_HOST: ${{ secrets.DEPLOY_HOST }}
+          DEPLOY_USER: ${{ secrets.DEPLOY_USER }}
+          DEPLOY_PATH: ${{ secrets.WEB_DEPLOY_PATH }}
+        run: node .build/deploy-to-server.js

+ 541 - 0
docs/实现/Nginx-Web部署代理配置.md

@@ -0,0 +1,541 @@
+# Nginx Web 部署代理配置指南
+
+本文档说明如何配置 Nginx 来托管 H5 应用,并代理 API 和 MQTT WebSocket 请求。
+
+## 目录
+
+- [基本配置](#基本配置)
+- [MQTT WebSocket 代理](#mqtt-websocket-代理)
+- [API 代理](#api-代理)
+- [HTTPS 配置](#https-配置)
+- [完整配置示例](#完整配置示例)
+- [故障排查](#故障排查)
+
+## 基本配置
+
+### 静态资源托管
+
+```nginx
+server {
+    listen 80;
+    server_name your-domain.com;  # 替换为你的域名
+
+    # H5 应用静态资源
+    location / {
+        root /var/www/html/web-releases/latest;  # 替换为你的 WEB_DEPLOY_PATH
+        index index.html;
+        try_files $uri $uri/ /index.html;  # SPA 路由支持
+        
+        # 缓存控制
+        location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
+            expires 1y;
+            add_header Cache-Control "public, immutable";
+        }
+        
+        # HTML 文件不缓存
+        location ~* \.html$ {
+            expires -1;
+            add_header Cache-Control "no-cache, no-store, must-revalidate";
+        }
+    }
+}
+```
+
+## API 代理
+
+### HTTP API 转发
+
+```nginx
+# API 代理配置
+location /api/ {
+    # 转发到后端 API 服务
+    proxy_pass http://localhost:6001/;  # 替换为你的后端 API 地址
+    
+    # 或者使用 upstream 配置负载均衡
+    # proxy_pass http://api_backend/;
+    
+    # 代理头设置
+    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;
+    
+    # 超时设置
+    proxy_connect_timeout 60s;
+    proxy_send_timeout 60s;
+    proxy_read_timeout 60s;
+    
+    # 缓冲设置(可选,根据需求调整)
+    proxy_buffering on;
+    proxy_buffer_size 4k;
+    proxy_buffers 8 4k;
+}
+```
+
+### Upstream 配置(可选)
+
+如果你有多个后端服务器,可以使用 upstream 配置负载均衡:
+
+```nginx
+upstream api_backend {
+    # 负载均衡策略
+    least_conn;  # 或 ip_hash
+    
+    # 后端服务器列表
+    server localhost:6001 weight=1 max_fails=3 fail_timeout=30s;
+    # server localhost:6002 weight=1 max_fails=3 fail_timeout=30s;
+    
+    # 健康检查(需要 nginx plus 或第三方模块)
+    # check interval=3000 rise=2 fall=3 timeout=1000;
+}
+
+location /api/ {
+    proxy_pass http://api_backend/;
+    # ... 其他配置
+}
+```
+
+## MQTT WebSocket 代理
+
+### 关键配置说明
+
+MQTT over WebSocket 需要特殊的 nginx 配置来支持 WebSocket 协议升级和长连接。
+
+```nginx
+# MQTT WebSocket 代理
+location /mqtt {
+    # 转发到 MQTT broker 的 WebSocket 端口
+    proxy_pass http://localhost:8083;  # 替换为你的 MQTT broker 地址
+    
+    # ===== WebSocket 升级必需配置 =====
+    proxy_http_version 1.1;
+    proxy_set_header Upgrade $http_upgrade;
+    proxy_set_header Connection "upgrade";
+    
+    # ===== 代理头设置 =====
+    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;
+    
+    # ===== 长连接超时设置(非常重要!)=====
+    # MQTT 是长连接协议,需要设置较长的超时时间
+    proxy_connect_timeout 60s;      # 初始连接超时
+    proxy_send_timeout 3600s;       # 发送超时(1小时)
+    proxy_read_timeout 3600s;       # 读取超时(1小时)
+    
+    # ===== 缓冲设置 =====
+    # 关闭缓冲,实现实时通信
+    proxy_buffering off;
+    
+    # ===== 可选:日志记录 =====
+    access_log /var/log/nginx/mqtt_access.log;
+    error_log /var/log/nginx/mqtt_error.log;
+}
+```
+
+### 配置说明
+
+1. **WebSocket 升级**:
+   - `proxy_http_version 1.1` - WebSocket 需要 HTTP/1.1
+   - `Upgrade` 和 `Connection` 头 - 实现协议升级
+
+2. **超时配置**:
+   - `proxy_read_timeout` 和 `proxy_send_timeout` 建议设置为 3600s(1小时)或更长
+   - MQTT 客户端通常使用心跳机制保持连接,如果心跳间隔是 30 秒,超时应该至少是心跳间隔的 2-3 倍
+
+3. **缓冲控制**:
+   - `proxy_buffering off` - 关闭缓冲以实现实时通信
+
+## HTTPS 配置
+
+### SSL/TLS 配置
+
+```nginx
+server {
+    listen 443 ssl http2;
+    server_name your-domain.com;
+
+    # SSL 证书配置
+    ssl_certificate /path/to/your/certificate.crt;
+    ssl_certificate_key /path/to/your/private.key;
+    
+    # SSL 协议和加密套件
+    ssl_protocols TLSv1.2 TLSv1.3;
+    ssl_ciphers HIGH:!aNULL:!MD5;
+    ssl_prefer_server_ciphers on;
+    
+    # SSL 会话缓存
+    ssl_session_cache shared:SSL:10m;
+    ssl_session_timeout 10m;
+    
+    # HSTS(可选,强制 HTTPS)
+    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
+    
+    # ... 其他配置(静态资源、API、MQTT)
+}
+
+# HTTP 重定向到 HTTPS
+server {
+    listen 80;
+    server_name your-domain.com;
+    return 301 https://$server_name$request_uri;
+}
+```
+
+### WebSocket over SSL (wss://)
+
+当使用 HTTPS 时,MQTT WebSocket 也会自动使用 wss:// 协议:
+
+```javascript
+// 前端代码自动适配
+const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
+const mqttUrl = `${protocol}//${window.location.host}/mqtt`;
+```
+
+## 完整配置示例
+
+### HTTP 版本(开发/测试环境)
+
+```nginx
+server {
+    listen 80;
+    server_name dev.your-domain.com;
+    
+    # 访问日志
+    access_log /var/log/nginx/zsis_access.log;
+    error_log /var/log/nginx/zsis_error.log;
+    
+    # H5 应用静态资源
+    location / {
+        root /var/www/html/web-releases/latest;
+        index index.html;
+        try_files $uri $uri/ /index.html;
+        
+        # 静态资源缓存
+        location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
+            expires 1y;
+            add_header Cache-Control "public, immutable";
+        }
+        
+        location ~* \.html$ {
+            expires -1;
+            add_header Cache-Control "no-cache, no-store, must-revalidate";
+        }
+    }
+    
+    # API 代理
+    location /api/ {
+        proxy_pass http://localhost:6001/;
+        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;
+        proxy_connect_timeout 60s;
+        proxy_send_timeout 60s;
+        proxy_read_timeout 60s;
+    }
+    
+    # MQTT WebSocket 代理
+    location /mqtt {
+        proxy_pass http://localhost:8083;
+        proxy_http_version 1.1;
+        proxy_set_header Upgrade $http_upgrade;
+        proxy_set_header Connection "upgrade";
+        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_connect_timeout 60s;
+        proxy_send_timeout 3600s;
+        proxy_read_timeout 3600s;
+        proxy_buffering off;
+    }
+}
+```
+
+### HTTPS 版本(生产环境)
+
+```nginx
+# HTTPS 服务器
+server {
+    listen 443 ssl http2;
+    server_name your-domain.com;
+    
+    # SSL 证书
+    ssl_certificate /etc/letsencrypt/live/your-domain.com/fullchain.pem;
+    ssl_certificate_key /etc/letsencrypt/live/your-domain.com/privkey.pem;
+    ssl_protocols TLSv1.2 TLSv1.3;
+    ssl_ciphers HIGH:!aNULL:!MD5;
+    ssl_prefer_server_ciphers on;
+    ssl_session_cache shared:SSL:10m;
+    ssl_session_timeout 10m;
+    
+    # 安全头
+    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
+    add_header X-Frame-Options "SAMEORIGIN" always;
+    add_header X-Content-Type-Options "nosniff" always;
+    add_header X-XSS-Protection "1; mode=block" always;
+    
+    # 访问日志
+    access_log /var/log/nginx/zsis_access.log;
+    error_log /var/log/nginx/zsis_error.log;
+    
+    # H5 应用静态资源
+    location / {
+        root /var/www/html/web-releases/latest;
+        index index.html;
+        try_files $uri $uri/ /index.html;
+        
+        location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
+            expires 1y;
+            add_header Cache-Control "public, immutable";
+        }
+        
+        location ~* \.html$ {
+            expires -1;
+            add_header Cache-Control "no-cache, no-store, must-revalidate";
+        }
+    }
+    
+    # API 代理
+    location /api/ {
+        proxy_pass http://localhost:6001/;
+        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;
+        proxy_connect_timeout 60s;
+        proxy_send_timeout 60s;
+        proxy_read_timeout 60s;
+    }
+    
+    # MQTT WebSocket 代理(wss://)
+    location /mqtt {
+        proxy_pass http://localhost:8083;
+        proxy_http_version 1.1;
+        proxy_set_header Upgrade $http_upgrade;
+        proxy_set_header Connection "upgrade";
+        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;
+        proxy_connect_timeout 60s;
+        proxy_send_timeout 3600s;
+        proxy_read_timeout 3600s;
+        proxy_buffering off;
+    }
+}
+
+# HTTP 重定向到 HTTPS
+server {
+    listen 80;
+    server_name your-domain.com;
+    return 301 https://$server_name$request_uri;
+}
+```
+
+## 故障排查
+
+### 常见问题
+
+#### 1. MQTT WebSocket 连接失败
+
+**症状**:前端无法连接到 MQTT broker
+
+**检查步骤**:
+
+```bash
+# 1. 检查 MQTT broker 是否运行
+netstat -tlnp | grep 8083
+
+# 2. 测试 WebSocket 连接(使用 websocat 工具)
+websocat ws://localhost/mqtt
+
+# 3. 查看 nginx 错误日志
+tail -f /var/log/nginx/mqtt_error.log
+
+# 4. 检查 nginx 配置
+nginx -t
+```
+
+**常见原因**:
+- `proxy_http_version 1.1` 未设置
+- `Upgrade` 和 `Connection` 头配置错误
+- 超时时间设置过短
+- MQTT broker 未启动或端口错误
+
+#### 2. API 请求 502 Bad Gateway
+
+**症状**:API 请求返回 502 错误
+
+**检查步骤**:
+
+```bash
+# 1. 检查后端 API 服务是否运行
+netstat -tlnp | grep 6001
+
+# 2. 测试后端 API
+curl http://localhost:6001/health
+
+# 3. 查看 nginx 错误日志
+tail -f /var/log/nginx/error.log
+```
+
+**常见原因**:
+- 后端服务未启动
+- `proxy_pass` 地址配置错误
+- 防火墙阻止连接
+
+#### 3. 静态资源 404
+
+**症状**:页面加载失败,静态资源找不到
+
+**检查步骤**:
+
+```bash
+# 1. 检查文件路径是否正确
+ls -la /var/www/html/web-releases/latest/
+
+# 2. 检查文件权限
+ls -la /var/www/html/web-releases/
+
+# 3. 检查符号链接
+readlink /var/www/html/web-releases/latest
+```
+
+**常见原因**:
+- 部署路径配置错误
+- 文件权限问题(nginx 用户无法读取)
+- 符号链接指向错误
+
+#### 4. CORS 错误
+
+如果你的后端 API 和前端不在同一域名下,需要配置 CORS:
+
+```nginx
+# 方式 1:在 nginx 配置 CORS
+location /api/ {
+    # ... 其他配置
+    
+    # CORS 头
+    add_header Access-Control-Allow-Origin $http_origin always;
+    add_header Access-Control-Allow-Methods 'GET, POST, PUT, DELETE, OPTIONS' always;
+    add_header Access-Control-Allow-Headers 'Authorization, Content-Type' always;
+    add_header Access-Control-Max-Age 86400 always;
+    
+    # OPTIONS 预检请求处理
+    if ($request_method = 'OPTIONS') {
+        return 204;
+    }
+}
+```
+
+### 测试工具
+
+#### 1. 测试 WebSocket 连接
+
+```bash
+# 使用 websocat(推荐)
+websocat ws://your-domain.com/mqtt
+
+# 使用 wscat
+wscat -c ws://your-domain.com/mqtt
+
+# 浏览器控制台测试
+const ws = new WebSocket('ws://your-domain.com/mqtt');
+ws.onopen = () => console.log('Connected');
+ws.onerror = (e) => console.error('Error:', e);
+```
+
+#### 2. 测试 API
+
+```bash
+# 测试 API 端点
+curl -v http://your-domain.com/api/health
+
+# 测试带认证的 API
+curl -v -H "Authorization: Bearer token" http://your-domain.com/api/data
+```
+
+#### 3. 查看实时日志
+
+```bash
+# 实时查看 nginx 访问日志
+tail -f /var/log/nginx/access.log
+
+# 实时查看 nginx 错误日志
+tail -f /var/log/nginx/error.log
+
+# 实时查看 MQTT 日志
+tail -f /var/log/nginx/mqtt_access.log
+```
+
+## 配置应用
+
+### 1. 创建配置文件
+
+```bash
+sudo nano /etc/nginx/sites-available/zsis
+```
+
+### 2. 启用配置
+
+```bash
+# 创建符号链接
+sudo ln -s /etc/nginx/sites-available/zsis /etc/nginx/sites-enabled/
+
+# 测试配置
+sudo nginx -t
+
+# 重载配置
+sudo nginx -s reload
+```
+
+### 3. 验证部署
+
+访问以下 URL 验证:
+- 静态资源:`http://your-domain.com/`
+- API:`http://your-domain.com/api/health`
+- MQTT:使用浏览器开发者工具查看 WebSocket 连接
+
+## 相关文档
+
+- [GitHub Actions Workflow](.github/workflows/build-web-deployment.yml)
+- [部署脚本](.build/deploy-to-server.js)
+- [Nginx 官方文档](https://nginx.org/en/docs/)
+- [MQTT over WebSocket](https://www.emqx.io/docs/en/latest/advanced/mqtt-over-websocket.html)
+
+## GitHub Secrets 配置
+
+需要在 GitHub 仓库中配置以下 secrets:
+
+| Secret 名称 | 说明 | 示例 |
+|------------|------|------|
+| `WEB_DEPLOY_PATH` | Web 部署目标路径 | `/var/www/html/web-releases` |
+| `DEPLOY_KEY` | SSH 私钥 | `-----BEGIN RSA PRIVATE KEY-----...` |
+| `DEPLOY_HOST` | 服务器地址 | `your-server.com` |
+| `DEPLOY_USER` | SSH 用户名 | `deploy` |
+
+## 部署流程
+
+1. **配置 GitHub Secrets**:在仓库设置中添加上述 secrets
+2. **配置 Nginx**:使用本文档中的配置模板
+3. **触发部署**:
+   - 推送代码到 master 分支
+   - 或手动触发 workflow
+4. **验证部署**:访问域名检查应用是否正常运行
+
+## 注意事项
+
+1. **超时配置**:MQTT WebSocket 需要较长的超时时间(至少 1 小时)
+2. **缓冲设置**:关闭 MQTT 的缓冲以实现实时通信
+3. **安全性**:生产环境建议使用 HTTPS(wss://)
+4. **监控**:配置日志记录和监控告警
+5. **备份**:定期备份 nginx 配置文件
+
+## 更新日志
+
+- 2025-01-03:创建初始版本
+- 包含 HTTP 和 HTTPS 配置示例
+- 添加 MQTT WebSocket 代理配置
+- 添加故障排查指南