在全栈开发中,如何在一台服务器上同时优雅地托管"纯静态官网"和"复杂的前后端分离项目"?如何处理图片上传路径错乱?如何解决 Safari 的 PWA 兼容性问题?
本文将毫无保留地分享我的上线实战经验,为你提供一份标准化的服务器架构与运维 SOP。
📁 服务器全局目录规范
在这台服务器上,我们同时托管两个项目,文件结构必须严格隔离,防止后期运维混乱:
- 项目一:工作室官网 (纯静态) -> 存放在
/var/www/studio/ - 项目二:全栈日历前端 -> 存放在
/var/www/calendar-frontend/ - 项目二:全栈日历后端 -> 存放在
/var/www/calendar-app/ - 项目二:用户真实上传文件库 -> 存放在
/var/www/calendar-app/uploads/
🛠️ 第一阶段:阿里云服务器初始化
1. 阿里云安全组 (防火墙)
- 必须放行端口:80 (HTTP), 443 (HTTPS), 22 (SSH)。
- 🚨 绝对禁止:禁止对外开放 Node.js 的 3001 端口!所有请求必须走 Nginx 内网转发,保护数据库与接口安全。
2. 安装全局环境
连上服务器终端,执行基础建设:
bash
# 1. 更新系统并安装 Nginx
apt update
apt install nginx -y
# 2. 删掉 Ubuntu 默认抢占 80 端口的测试网页配置
rm /etc/nginx/sites-enabled/default
systemctl restart nginx
# 3. 安装 Node.js (v20 环境)
curl -fsSL https://deb.nodesource.com/setup_20.x | bash -
apt install -y nodejs
# 4. 安装进程守护神器 PM2 与 TS 运行环境
npm install -g pm2 ts-node typescript
🖥️ 第二阶段:部署项目一 (纯静态官网)
示例绑定主域名:xy-d.top 和 www.xy-d.top
1. 上传文件与赋予权限
用 FileZilla 将本地打包好的前端文件(dist 文件夹内容),上传到服务器的 /var/www/studio/ 目录。
bash
mkdir -p /var/www/studio
# 确保 Nginx 拥有读取权限,防止 403 Forbidden 报错
chown -R www-data:www-data /var/www/studio
chmod -R 755 /var/www/studio
2. 配置 Nginx 路由
bash
nano /etc/nginx/sites-available/studio
写入以下配置,开启 History 路由支持:
nginx
server {
listen 80;
server_name xy-d.top www.xy-d.top;
root /var/www/studio;
index index.html;
location / {
try_files $uri $uri/ /index.html;
}
}
激活网站:
bash
ln -s /etc/nginx/sites-available/studio /etc/nginx/sites-enabled/
⚙️ 第三阶段:部署项目二 (React + Node + Prisma 全栈项目)
示例绑定二级域名:calendar.xy-d.top
1. 后端部署与数据迁移
用 FileZilla 将后端代码上传至 /var/www/calendar-app(切记:排除本机的 node_modules )。将开发环境的 SQLite 数据库 dev.db 覆盖到 server/prisma/ 目录下。
bash
cd /var/www/calendar-app
# 重新安装 Linux 环境专属依赖
npm install
# 强力同步数据库结构 (自动补齐新表,无损同步)
npx prisma generate --schema=./server/prisma/schema.prisma
npx prisma db push --schema=./server/prisma/schema.prisma
💡 前端环境变量提醒 (极度重要):
确保前端
.env.production中的接口地址为相对路径VITE_API_BASE_URL=/api或线上真实域名,切勿写localhost!
2. 解决图片上传 500 报错(软连接魔法)
Node.js 运行目录不同常导致图片上传路径迷路,建议用软连接做路径穿透:
bash
# 建立根目录真实存储库并赋予最高权限
mkdir -p /var/www/calendar-app/uploads
chmod -R 777 /var/www/calendar-app/uploads
# 进入 server 目录,建立传送门指向真实物理目录
cd /var/www/calendar-app/server
rm -rf uploads # 删掉可能导致冲突的空文件夹
ln -s /var/www/calendar-app/uploads uploads
3. 启动后端进程 (避坑 TS 解析限制)
bash
cd /var/www/calendar-app/server
# 让 PM2 代理执行 npm run start,完美绕过 Node v20 的 ESM 模块限制
pm2 start npm --name "calendar-api" -- run start
# 保存状态,设置开机自启
pm2 save
pm2 startup
4. 前端自动化编译部署
bash
cd /var/www/calendar-app
npm install
npm run build
# 将打包好的文件移交给 Nginx 专属前端目录
mkdir -p /var/www/calendar-frontend
rm -rf /var/www/calendar-frontend/*
cp -r dist/* /var/www/calendar-frontend/
# 赋予权限
chown -R www-data:www-data /var/www/calendar-frontend
chmod -R 755 /var/www/calendar-frontend
🌐 第四阶段:全局 Nginx 配置与一键 HTTPS
1. 修改全局上传大小限制 (防止上传大图片报 413 Request Entity Too Large)
bash
nano /etc/nginx/nginx.conf
# 找到 http { ... } 块,在里面加上:
client_max_body_size 50M;
2. 配置全栈项目路由
bash
nano /etc/nginx/sites-available/calendar
nginx
server {
listen 80;
server_name calendar.xy-d.top;
# 1. 前端页面
root /var/www/calendar-frontend;
index index.html;
location / {
try_files $uri $uri/ /index.html;
}
# 2. 接口反向代理 (转发给本地 3001 端口)
location /api {
proxy_pass http://127.0.0.1:3001;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
# 3. 静态附件防盗链与缓存穿透
location /uploads {
proxy_pass http://127.0.0.1:3001;
}
}
3. 激活网站与 HTTPS 加密
bash
ln -s /etc/nginx/sites-available/calendar /etc/nginx/sites-enabled/
nginx -t
systemctl restart nginx
# 安装 Certbot 并一键配置 SSL 证书
apt install certbot python3-certbot-nginx -y
certbot --nginx
# 提示 Redirect 时,务必选 2 (强制 HTTPS)
🔄 第五阶段:日常维护与无损更新 (SOP 手册)
形成肌肉记忆的无宕机更新流程:
🛠️ 场景一:更新【全栈项目】的前端页面
-
源码覆盖到服务器
/var/www/calendar-app/。 -
终端执行:
bashcd /var/www/calendar-app npm run build cp -rf dist/* /var/www/calendar-frontend/
🛠️ 场景二:修改了【全栈项目】的后端逻辑 (如增删 API)
- 源码覆盖到
/var/www/calendar-app/server。 - 重启守护进程:
pm2 restart calendar-api
🛠️ 场景三:修改了数据库表结构 (schema.prisma)
bash
cd /var/www/calendar-app
npx prisma generate --schema=./server/prisma/schema.prisma
npx prisma db push --schema=./server/prisma/schema.prisma
pm2 restart calendar-api
⚠️ 第六阶段:经典踩坑与破案实录 (高价值经验)
回顾本次部署经历的核心三大坑:
- "验证码发送失败" (502 Bad Gateway 案)
- 真相 :Node v20 对 ES Modules 极度严格,原生 PM2 跑
.ts经常崩溃。 - 破案 :用
pm2 start npm -- run start代理执行原生 TS 命令,完美解决。
- 真相 :Node v20 对 ES Modules 极度严格,原生 PM2 跑
- "旧数据迁移后,手机端登录彻底白屏" (全场最难案)
- 真相 :iOS Safari 对安全极其严格------普通网页不支持
NotificationAPI,强制调用会导致 JS 渲染树当场崩溃 。且 PWA (sw.js) 顽固缓存了老旧代码。 - 破案 :调用任何浏览器底层 API 必须加生存判定
if ('Notification' in window);移动端白屏排查神器:在index.html引入vConsole抓取报错。
- 真相 :iOS Safari 对安全极其严格------普通网页不支持
🛡️ 第七阶段:数据灾备安全 (保命底线)
对于 SQLite 单文件数据库,备份极其简单。建议定期下载以下两个文件进行冷备份:
- 用户文字与关系数据 :
/var/www/calendar-app/server/prisma/dev.db - 用户上传的真实附件 :
/var/www/calendar-app/uploads/文件夹
有了这两个文件,即便服务器物理损毁,也能在 15 分钟内满血换机复活!
🎉 见证部署成果:XYD-Calendar 正式上线!
上面这套硬核的架构,正是我为了支撑我的最新全栈独立开发项目------XYD-Calendar (玄宇日程笔记) 而打造的。
这是一个专为打工人和科研/学生党 设计的 「日程管理 + 极致排版笔记 + AI 工作流」 All-in-One 效率神器。
🌟 核心杀手锏功能:
- 🤖 AI 职场黑话写周报:平时随手在日历记流水账,周五点击"AI 撰写汇报",系统自动调取大模型,一键将你的工作包装成带有"赋能、闭环、抓手"等高大上词汇的专业周报!(SVIP支持绑定自己的 OpenAI / DeepSeek Key,无限次使用!)
- 📐 Markdown + LaTeX 极致排版:全面开放 HTML 标签安全渲染。支持折叠面板、荧光笔高亮、以及科研必备的 KaTeX 复杂数学公式渲染。
- 📄 真正的商业级导出 :
- PDF 导出 :浏览器原生矢量渲染,代码块自动换行,图片与表格绝对不被腰斩截断!
- Word 导出:底层 AST 语法树解析,完美保留大纲、表格与 LaTeX 公式。
- 📱 跨平台 PWA 支持:手机端无缝当做独立 App 使用,双端数据实时同步。
🎁 CSDN 专属粉丝福利:
目前项目已正式开放注册!为了感谢大家的阅读,特开启邀请裂变福利:
👉 访问官网立即体验 :[https://calendar.xy-d.top/?invite=DLKCTB\]
💡 在注册时填写我的专属邀请码 :【DLKCTB】
填写邀请码注册成功后,系统将自动为您发放 7 天的高级 VIP 权益,立刻解锁 AI 写周报、高级排版导出等全部核心特权!
(如果你觉得这个工具好用,也可以在个人中心生成你的专属邀请链接发给同事,每邀请一人,双方均可无上限叠加 7 天 VIP!)
欢迎大家来白嫖体验,在评论区留下你的使用反馈和改进建议!👇