首页›分类文章›计算机技术›web 开发›阿里云 ECS 部署 Next.js:从本机到线上

阿里云 ECS 部署 Next.js:从本机到线上

计算机技术 · web 开发2026-09-192次浏览0 个评论

本篇是《手写一个内容型技术博客站》系列第 8 篇。

代码写完了,最刺激的部分来了:上线。这篇讲从阿里云 ECS 到域名全链路的部署实践,重点是不踩坑——有些坑踩一次,数据和服务能疼很久。

一、部署拓扑总览

text
用户浏览器
   │ https 443
   ▼
Apache(反向代理 + HTTPS 证书)
   │ http 127.0.0.1:<端口>
   ▼
Node (next start, pm2 托管)
   │ 读文件
   ▼
src/content/ + src/data/(磁盘)

为什么 Apache 挡在 Node 前面:让 Apache 处理 443/证书/静态资源/安全头,Node 专注业务。Next.js 的 next start 直接暴露公网不是不行,但把透传、缓存、防护都交给久经考验的 Apache/Nginx 更稳。

二、铁律:node_modules 永不拷/rsync 上传

这是部署最重要的纪律。

为什么:node_modules 里有大量平台相关二进制(@next/swc 等)和符号链接(.bin/next)。从本机拷贝/rsync 上传时不加 -l,符号链接会变成普通坏文件;跨平台二进制不兼容。服务器跑 next 时:

text
Cannot find module '../server/require-hook'
Require stack: .../node_modules/.bin/next

就是这个根因——.bin/next 软链坏了。

正确做法:

text
# 代码同步(排除 node_modules/.next/运行时数据)
rsync -avz --exclude node_modules --exclude .next \
      --exclude 'src/data/comments' ./ user@host:/srv/nextjs-jiusi/

# 服务器上装依赖(保留软链 + postinstall)
cd /srv/nextjs-jiusi
rm -rf node_modules && npm ci

铁律:部署流程只 rsync 代码,依赖一律服务器 npm ci。

三、进程管理:pm2

Node 服务用 pm2 托管,好处是崩溃自动重启、日志轮转、开机自启。

bash
# 启动(关键:--update-env 让 pm2 重载环境变量)
pm2 start npm --name nextjs-jiusi -- start
pm2 restart nextjs-jiusi --update-env

# 开机自启
pm2 startup
pm2 save

日志轮转

pm2 日志无限增长会撑爆磁盘。用 pm2-logrotate 或系统 logrotate:

bash
pm2 install pm2-logrotate
pm2 set pm2-logrotate:max_size 10M
pm2 set pm2-logrotate:retain 30

配置要点(skill 实测):size 10M + daily 双触达——只配 size 不配 daily,日志量小则 main log 长期不轮转,maxage 清理永不执行。

四、Apache 反向代理

apache
# /etc/apache2/sites-available/your-site.conf
<VirtualHost *:443>
    ServerName chahuawu.com
    # HTTPS 证书配置...

    # 反向代理到本地 Node
    ProxyPreserveHost On
    ProxyPass / http://127.0.0.1:8000/
    ProxyPassReverse / http://127.0.0.1:8000/

    # 透传真实 IP(Node 做 IP 去重需要)
    RequestHeader set X-Forwarded-For "%{REMOTE_ADDR}s"
    RequestHeader set X-Forwarded-Proto "https"
</VirtualHost>

X-Forwarded-For 必须设——评论/IP 去重、访问量统计依赖真实 IP,Apache 反代不设的话 Node 看到的是 127.0.0.1。

五、自动重建:auto_rebuild.py

"新增文章要 build"不能靠 SSH 手动。auto_rebuild.py 轮询 src 变化自动构建重启:

bash
# scripts/auto_rebuild.py
# 轮询 3s,监控 src/ + public/ + next.config.ts + package.json + tsconfig.json
# 排除 src/data/comments(运行时数据,写入不触发重建)
# 检测到变化 → rm -rf .next && next build → 重启 server

配合 systemd 或 nohup 常驻。这样生产上新内容 = 上传 md 文件 → 自动 build → 刷新可见。

六、同源问题:本地好好的,线上 404

这个坑几乎每个人都会遇到,讲透它。

症状:本地 next start 一切正常,上传后线上某个详情页 404。

真相:Next.js 的 SSG 详情页(文章、静态页)是 build 时预渲染的。如果你本件构建的产物(.next)没有同步到服务器,或者线上 build 时内容没到位,服务器就没有对应 slug 的预渲染 HTML。

关键:SSG 页面必须 build 时才生成,且 dynamicParams=false 时未枚举的 slug 永远 404。

排查顺序:

bash
# 1. 确认线上 .next 是线上 build 的,不是拷贝的
ls .next/server/app/posts/    # 看有没有对应 slug 的 html

# 2. 确认线上内容文件到位
ls src/content/categories/.../<slug>.md

# 3. 确认 build 是 rm -rf .next 后的干净构建

ISR 救不了新 slug:revalidate=600 只重建"已枚举 slug"的内容,不会重新枚举 generateStaticParams。新增文章后必须完整 rebuild。

上线顺序纪律:先 build + 重启,再让新内容可点击;否则列表(动态)能点进去,详情页(SSG)404。

七、部署检查清单

text
□ 代码同步:rsync 代码(排除 node_modules/.next/运行时数据)
□ 服务器 npm ci:rm -rf node_modules && npm ci
□ 环境变量:.env.local / 环境变量就位(Basic Auth 凭据等)
□ 干净构建:rm -rf .next && npm run build
□ 数据备份:src/data/(评论/阅读数/访问统计)先备份再覆盖
□ 启动与守护:pm2 restart --update-env
□ 冒烟测试:curl 关键路由(首页/文章/教程/API)
□ 日志:大小/保留天数配置

部署的本质:把你的"本地能跑"变成"线上能持续跑"。多一份 checklist,少一次深夜事故。


给普通人的一句话:上线不是一个动作,而是一套"把你的代码安全地搬进生产环境并让它活下来"的纪律。

参考

  • Next.js 部署文档:https://nextjs.org/docs/app/building-your-application/deploying

评论

0

评论加载中…

发表评论

0/2000