基于GitHub Workflow的大型SPA项目CI/CD配置问题咨询
大型SPA项目GitHub CI配置优化疑问
技术栈
- TypeScript + Vue.js
- 带WebSocket与API代理的Webpack Dev Server
- Playwright做E2E测试,Mock所有服务端调用(含WebSocket)
项目背景:前端依赖丰富,未缓存时单次构建耗时约10分钟,产物200MB,需尽可能减少构建次数。
当前PR触发流程
- 运行ESLint
- 执行单元测试
- 安装依赖(已配置缓存)
- 恢复Webpack缓存(若存在)
- 在Webpack Dev Server上运行Playwright测试(通过代理与WebSocket拦截实现API Mock)
- 构建产物并部署至独立服务器
核心疑问
- 是否应该先构建SPA,再通过其他HTTP服务器部署产物并处理代理/WebSocket调用?如果可行,如何针对E2E测试执行该构建?
- 不新增Vercel等第三方基础设施的前提下,有没有针对独立服务器的部署预览方案,或者直接通过GitHub实现预览?
已尝试方案
- 全程依赖Webpack构建,每次耗时15-20分钟,效率极低;
- 运行Webpack Dev Server并尝试提取产物,但dist文件夹会被自动清空;
- Webpack构建后用http-server部署,但缺失WebSocket服务支持,代理功能表现不理想。
解决方案建议
针对疑问1:构建产物后用独立服务器做E2E测试
完全可行,核心思路是一次构建同时满足E2E测试和部署需求,具体步骤如下:
- 调整Webpack配置,生成带Mock能力的测试构建产物
- 新增
test环境配置,通过环境变量(如process.env.NODE_ENV === 'test')区分生产/测试构建,保留API代理和WebSocket的Mock逻辑。比如在Vue项目的vue.config.js中,注入Mock中间件,或把Playwright需要的Mock逻辑打包进测试产物(客户端Mock场景)。 - 确保测试构建与生产构建差异最小,仅保留Mock必要逻辑,避免额外构建开销。
- 新增
- 使用支持WebSocket和代理的自定义HTTP服务器
- 放弃http-server,用
express编写轻量服务器,同时实现静态托管、API代理和WebSocket Mock:const express = require('express'); const http = require('http'); const WebSocket = require('ws'); const { createProxyMiddleware } = require('http-proxy-middleware'); const app = express(); // 托管构建产物 app.use(express.static('dist')); // 配置API代理指向Mock服务 app.use('/api', createProxyMiddleware({ target: 'http://your-mock-server', changeOrigin: true })); const server = http.createServer(app); // 启动WebSocket服务并处理Mock逻辑 const wss = new WebSocket.Server({ server }); wss.on('connection', (ws) => { ws.on('message', (data) => { // 根据请求返回Mock数据 ws.send(JSON.stringify({ mockType: 'ws-data', content: 'mock-content' })); }); }); server.listen(3000, () => console.log('Test server running on port 3000')); - 将该脚本加入项目依赖,CI中构建完测试产物后启动服务器,再运行Playwright测试。
- 放弃http-server,用
- 优化CI流程
- 恢复Webpack缓存后,先执行一次测试构建生成带Mock的dist产物,启动自定义服务器完成Playwright测试;测试通过后,复用本次构建缓存快速生成生产产物(或直接用测试产物调整后部署),避免重复构建。
针对疑问2:无额外基础设施的部署预览方案
有两种实用方向:
- 独立服务器多PR目录/子域名预览
- 在独立服务器上为每个PR分配专属子目录(如
/var/www/pr-123),CI中用scp或rsync将构建产物上传至对应目录; - 提前配置Nginx通配符子域名(如
pr-*.yourdomain.com),通过CI脚本动态生成Nginx配置(映射子域名到对应PR目录),执行nginx -s reload生效。这种方式能完整保留WebSocket和代理功能,适合正式预览。
- 在独立服务器上为每个PR分配专属子目录(如
- GitHub Pages + 客户端Mock预览
- 将PR构建产物上传至GitHub Pages的临时分支(如
pr-123-pages),利用GitHub Pages托管静态资源; - 若需WebSocket功能,在预览构建中客户端Mock所有WebSocket调用,仅用于UI交互预览,适合快速验证页面效果。
- 将PR构建产物上传至GitHub Pages的临时分支(如
内容的提问来源于stack exchange,提问作者Revolist
相关产品推荐
相关产品推荐

