前天六點多,我的博客伺服器掛了。儘管阿里雲給我發了告警提示,但是絲毫沒有用處。當我日常在我的互聯網 2C2G3M 領地巡遊,郎當哩個兒郎,發現只有首頁可以看,其他的頁面都是 504 Gateway-Timeout,咚咚錵咚咚錵,看了看阿里雲的監控,原來是內存洩漏,現在內存爆了,錵錵錵錵錵錵,讓我看看是誰的鍋,咚咚咚咚咚咚,咚不起來了,連不上 ssh 了。
已經不是一般的故障了,必須要出重拳,才能收回我的 2C 可用 0G3M 的領地了。
強制重啟下,內存使用也降下來了,正好可以把我的博客前後端更新一下,我的部署參考了玖月的教程,具體是這個和這個,當然我上的是殘缺版,能用就行。
使用 docker 更新後端很簡單啊,不多贅述,總之叮鈴哐啷地升級完成。更新前端就不太好了,build 需要比較大的內存,上次的方法是用阿里雲按量付費租個內存夠大的機器,然後內網一頓傳。可惜今時不同往日,我已經有了本地的 ubuntu 備用機了,何必漲阿里志氣。
事實比較遺憾,如果要一股腦全部傳過去,外網 3M 的小水管還是用不太夠,何況我的網絡上傳速度又比較遺憾,難道重蹈覆轍?
閱讀以下內容前建議先閱讀Mix-Space 部署最新前端 Shiro
感謝 Shiro 項目使用的 Next.js 的先進特性,翻了翻項目的 next.config.mjs
,發現它配置了 output: 'standalone'
!這個簡直是我需要的神兵利器!它會在 next build
之後,聰明地只打包那些真正需要的依賴文件(連 node_modules
都會來個 “瘦身版”),然後一股腦兒塞進 .next/standalone
目錄,出來的就是個超迷你的構建包!
贏
// 項目中的 next.config.mjs 長這樣:
/** @type {import('next').NextConfig} */
const nextConfig = {
output: 'standalone', // 就是這行!
// ... 其他配置
};
export default nextConfig;
項目裡還有一個打包腳本,可以自動化地打包 standalone
模式的輸出,使其可以直接用於部署。
贏贏
#!env bash
set -e
CWD=$(pwd)
cd .next # 進入構建輸出目錄
rm -rf cache # 清理構建緩存
cp -r ../public ./standalone/public # 將 public 靜態資源複製到 standalone 目錄
cd ./standalone # 進入 standalone 目錄
echo ';process.title = "Shiro (NextJS)"' >>server.js # 添加進程標題
mv ../static/ ./.next/static # 移動服務端必需的靜態資源 (供 standalone server 使用)
cp $CWD/ecosystem.standalone.config.cjs ./ecosystem.config.js # 複製 PM2 配置文件
cd .. # 返回 .next 目錄
mkdir -p $CWD/assets
rm -rf $CWD/assets/release.zip
zip --symlinks -r $CWD/assets/release.zip ./* # 壓縮整個準備好的 .next 文件夾
腳本把優化過的 standalone
輸出拿過來,再把 PM2 配置、靜態資源這些 “佐料” 加上,最後變出一個 assets/release.zip
的壓縮包,就可以方便地傳輸部署了。
贏贏贏
理論可行,接下來就是實操了。
開發機做什麼#
首先安裝好 pnpm,然後在項目根目錄下運行
pnpm install # 或者 pnpm i
pnpm build
這時就會跑 next build
,然後噌噌噌噌地生成 .next
文件夾,裡面就有我們心心念念的 .next/standalone
然後
bash standalone-bundle.sh
就噔噔噔噔端出一個 assets/release.zip
部署包。🥳
最後把這個壓縮包發送到伺服器上,開發機的任務可以說就大功告成了。
伺服器做什麼#
首先要有適當版本的 node.js 與 PM2,同時給夠權限。
sudo mkdir -p /srv/shiro-app
sudo chown -R user:usergroup /srv/shiro-app # 給自己授權
cd /srv/shiro-app
sudo unzip /放壓縮包的路徑/release.zip
然後進入 standalone
目錄, server.js
和 ecosystem.config.js
都在這裡。
cd standalone
pm2 start ecosystem.config.js
這下真是大功告成了,不過之前部署一直出錯,最後排查半天發現是寫錯了.env
裡的域名,大失敗。