如何在自有服务器上无中断正确部署SvelteKit应用?
无中断部署SvelteKit应用(PM2+Ubuntu)
1. 修正生产环境启动方式
生产环境不要用npm run preview(该命令仅用于本地预览构建产物),直接运行SvelteKit构建后的Node入口文件,更高效且符合生产规范:
- 构建完成后,产物在
build目录,入口逻辑可通过自定义启动文件管理 - 修改
ecosystem.config.cjs的生产应用配置:
module.exports = { apps: [ { name: "app_sistamu", // 替换为自定义启动文件(下文会创建) script: "./server.js", args: "--port 8080", watch: false, instances: "max", exec_mode: "cluster", // 配置优雅重启参数,避免强制终止用户请求 kill_timeout: 5000, wait_ready: true, listen_timeout: 10000 }, // 开发环境配置保留 { name: "app_sistamu_DEV", script: "npm", args: "run dev -- --host --port 5173", out_file: "/dev/null", watch: false } ], };
2. 实现零停机部署的核心方案
方案一:PM2优雅重载+预构建验证
先完成构建和可用性验证,再触发PM2的优雅重载,确保新进程就绪后才替换旧进程:
# 合并代码分支 git merge -m "Merge development to master" development # 仅安装生产依赖(减少构建时间) npm install --production # 构建应用 npm run build # 临时启动新构建的服务,验证可用性 node ./server.js --port 8081 & TEST_PID=$! sleep 5 # 测试服务是否正常响应 curl -s http://localhost:8081 > /dev/null if [ $? -eq 0 ]; then # 验证通过,终止临时进程 kill $TEST_PID # 触发PM2优雅重载,自动完成新旧进程切换 pm2 reload app_sistamu --update-env else # 验证失败,终止临时进程并中断部署 kill $TEST_PID echo "Build verification failed, deployment aborted" exit 1 fi
关键参数说明:
--update-env:重载时同步更新环境变量- PM2配置中的
wait_ready:等待进程发送ready信号后才标记为在线 kill_timeout:给旧进程预留处理完现有请求的时间
方案二:蓝绿部署(绝对零停机)
如果对可用性要求极高,可采用蓝绿部署,通过反向代理(如Nginx)切换流量:
- 修改
ecosystem.config.cjs,添加蓝绿两个环境的配置:
module.exports = { apps: [ { name: "app_sistamu_BLUE", script: "./server.js", args: "--port 8080", exec_mode: "cluster", instances: "max" }, { name: "app_sistamu_GREEN", script: "./server.js", args: "--port 8081", exec_mode: "cluster", instances: "max" }, // 开发环境配置保留... ] };
- 部署脚本逻辑:
git merge -m "Merge development to master" development npm install --production npm run build # 读取Nginx配置,确定当前活跃环境 ACTIVE_ENV=$(grep -o "app_sistamu_[A-Z]*" /etc/nginx/sites-available/your-app.conf | head -1) DEPLOY_ENV="app_sistamu_GREEN" DEPLOY_PORT=8081 if [ "$ACTIVE_ENV" = "app_sistamu_GREEN" ]; then DEPLOY_ENV="app_sistamu_BLUE" DEPLOY_PORT=8080 fi # 启动新环境的应用 pm2 start ecosystem.config.cjs --only $DEPLOY_ENV # 等待服务启动并验证可用性 sleep 10 curl -s http://localhost:$DEPLOY_PORT > /dev/null if [ $? -eq 0 ]; then # 更新Nginx配置,切换流量到新环境 sed -i "s/app_sistamu_[A-Z]*/$DEPLOY_ENV/g" /etc/nginx/sites-available/your-app.conf nginx -s reload # 停止旧环境的应用 pm2 stop $ACTIVE_ENV else # 验证失败,清理新环境进程 pm2 stop $DEPLOY_ENV echo "Deployment failed, rolling back" exit 1 fi
3. 配置SvelteKit发送就绪信号
让PM2准确识别进程启动状态,需在项目根目录创建server.js:
import { handler } from './build/handler.js'; import express from 'express'; const app = express(); const port = process.argv[2] ? process.argv[2].split('=')[1] : 8080; app.use(handler); const server = app.listen(port, () => { console.log(`Server running on port ${port}`); // 向PM2发送就绪信号 if (process.send) { process.send('ready'); } }); // 处理优雅关闭,确保完成现有请求后再终止 process.on('SIGTERM', () => { console.log('SIGTERM received, shutting down gracefully'); server.close(() => { console.log('Server closed'); process.exit(0); }); });
同时修改svelte.config.js的adapter配置,适配环境变量:
adapter: adapter({ out: 'build', precompress: false, envPrefix: 'APP_', polyfill: true }),
4. 补充优化建议
- 配置PM2日志:在
ecosystem.config.cjs中添加error_file和out_file参数,方便排查部署问题 - Nginx静态缓存:在反向代理层启用静态资源缓存,降低应用服务器压力
- 自动化CI/CD:结合GitHub Actions或GitLab CI实现自动构建、验证和部署,减少手动操作误差
内容的提问来源于stack exchange,提问作者Ichwanul Fadhli
相关产品推荐
相关产品推荐

