Nextjs 启用standalone构建部署
默认nextjs是启动export模式,这个模式体量巨大且严重依赖build时的环境,即你如果在本地build,妄想把.next package.json等部署需要的文件单独上传到服务器然后执行部署,此时虽然能部署成功,但是访问页面会发现有水合错误的提示,服务器端渲染和客户端不一致的问题。next要求build构建和部署必须在同一个环境里,否则就会出现环境不一样导致的水合错误。
所以现在除非你直接服务器端打包构建再部署,不然就一定会出问题。
但是服务器打包压力会很大,对于这种实时渲染的应用,像我这个才2G且还运行了mysql的土豆服务器会直接崩掉。
所以nextjs也提供了另一种方案,即本地使用standalone的方式打包构建,构建成功之后直接copy .next里的standalone文件夹和static public等文件夹 然后在standalone里新建一个.next文件夹,把static复制到这个.next文件夹里。此时部署只需要执行standalone里的server.js文件就能部署服务里,因为nextjs已经把依赖打包进standalone里了,再也不需要依赖node_modules里的模块。
即:
root
| standalone构建的产物
| .next
| static
我使用了workflow,所以我只需要修改upload的那一步把文件整理成我想要的结构并上传到服务器里
如果不理解我的文字也可以看我上传了什么东西:
- name: 上传 standalone 构建产物 + 静态资源 + public
run: |
# 1. 清空服务器旧部署
ssh -i ~/.ssh/id_rsa_deploy -o StrictHostKeyChecking=no \
${{ secrets.SERVER_USER }}@${{ secrets.SERVER_HOST }} \
"rm -rf /var/www/frontend/blog/*"
# 2. 上传 standalone 文件夹内容(server.js + node_modules + package.json 等)
rsync -avz -e "ssh -i ~/.ssh/id_rsa_deploy -o StrictHostKeyChecking=no" \
.next/standalone/ \
${{ secrets.SERVER_USER }}@${{ secrets.SERVER_HOST }}:/var/www/frontend/blog/
# 3. 上传 .next/static 到正确位置
rsync -avz -e "ssh -i ~/.ssh/id_rsa_deploy -o StrictHostKeyChecking=no" \
.next/static/ \
${{ secrets.SERVER_USER }}@${{ secrets.SERVER_HOST }}:/var/www/frontend/blog/.next/static/
# 4. 上传 public
rsync -avz -e "ssh -i ~/.ssh/id_rsa_deploy -o StrictHostKeyChecking=no" \
public/ \
${{ secrets.SERVER_USER }}@${{ secrets.SERVER_HOST }}:/var/www/frontend/blog/public/
补充(可能会踩的坑
如果你之前是默认构建部署的方案,那你配置的nginx一定是监听ipv6的 即proxy_pass http://[::]:3000
因为现在nextjs默认是开启ipv6的,如果不这么写你的nginx肯定无法代理。
但是现在你已经改成了standalone 启动服务是直接启动server.js的,此时开启的服务是ipv4的,所以记得去/etc/nginx/sites-available/xx里修改nginx配置,改成127.0.0.1:3000
不然访问又是502了