- Published on
GitHub ActionsでblogをNginxにdeployする
- Authors
- Name
- Nomad Dev Life
JavaScript heap out of memory
まだ3記事目だというのに、Webサーバー上でNext.jsのブログをyarn build
すると"JavaScript heap out of memory"が発生し、buildできなくなりました…。
? Compiled successfully
Linting and checking validity of types . ? TypeScript project references are not fully supported. Attempting to build in incremental mode.
Linting and checking validity of types .
<--- Last few GCs --->
[295983:0x71075a0] 62412 ms: Scavenge 472.8 (485.6) -> 472.5 (486.9) MB, 12.6 / 0.0 ms (average mu = 0.760, current mu = 0.650) allocation failure;
[295983:0x71075a0] 62580 ms: Scavenge 473.5 (486.9) -> 473.2 (491.4) MB, 103.4 / 0.0 ms (average mu = 0.760, current mu = 0.650) allocation failure;
<--- JS stacktrace --->
FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory
1: 0xb85bc0 node::Abort() [/home/user/.nvm/versions/node/v18.18.2/bin/node]
2: 0xa94834 [/home/user/.nvm/versions/node/v18.18.2/bin/node]
3: 0xd66d10 v8::Utils::ReportOOMFailure(v8::internal::Isolate*, char const*, bool) [/home/user/.nvm/versions/node/v18.18.2/bin/node]
4: 0xd670b7 v8::internal::V8::FatalProcessOutOfMemory(v8::internal::Isolate*, char const*, bool) [/home/user/.nvm/versions/node/v18.18.2/bin/node]
5: 0xf447c5 [/home/user/.nvm/versions/node/v18.18.2/bin/node]
6: 0xf56cad v8::internal::Heap::CollectGarbage(v8::internal::AllocationSpace, v8::internal::GarbageCollectionReason, v8::GCCallbackFlags) [/home/user/.nvm/versions/node/v18.18.2/bin/node]
7: 0xf313ae v8::internal::HeapAllocator::AllocateRawWithLightRetrySlowPath(int, v8::internal::AllocationType, v8::internal::AllocationOrigin, v8::internal::AllocationAlignment) [/home/user/.nvm/versions/node/v18.18.2/bin/node]
8: 0xf32777 v8::internal::HeapAllocator::AllocateRawWithRetryOrFailSlowPath(int, v8::internal::AllocationType, v8::internal::AllocationOrigin, v8::internal::AllocationAlignment) [/home/user/.nvm/versions/node/v18.18.2/bin/node]
9: 0xf1394a v8::internal::Factory::NewFillerObject(int, v8::internal::AllocationAlignment, v8::internal::AllocationType, v8::internal::AllocationOrigin) [/home/user/.nvm/versions/node/v18.18.2/bin/node]
10: 0x12d8caf v8::internal::Runtime_AllocateInYoungGeneration(int, unsigned long*, v8::internal::Isolate*) [/home/user/.nvm/versions/node/v18.18.2/bin/node]
11: 0x1705b39 [/home/user/.nvm/versions/node/v18.18.2/bin/node]
Linting and checking validity of types ..
Tailwind CSS BlogのIssueを見ると、"12500ページのbuildだとメモリ16GBではbuildできない"とか、"100ページ超でも8GBでは足りない"という話がでています。SSGはコンテンツ生成時にかなりメモリを使うようですね。
確かにWebサーバーのランニングを安く上げる為にスペックをケチっているのですが、それにしても3記事目でダメか…と。
WebサーバーはVPSなのでスペックを上げることはできるのですが、ランニングは少しでも安い方が助かります。ですので、今回はGitHub Actionを使い、GitHub上でbuildして、生成したhtml等をWebサーバーにdeployしてみることにしました。
イメージ
今回は、git push
したらGitHub Actionsでyarn build
し、成果物(out)をVPSにSSH/SCPでdeployしたいと思います。イメージは以下です。
Webサーバーは、24時間立ち上げっぱなしなのでVultr VPSにdeployしています。そのおかげでサーバー代は月¥1,000もかかっていません😄
SSH/SCPの準備
GitHub ActionsからWebサーバーにコンテンツをdeployする際に、SSH/SCPを使います。その為、GitHub Actionsに事前にSSH鍵を登録しておく必要があります。予めSSH鍵を作成し、その鍵でdeploy先のサーバーにSSH接続できることを確認しておいてください。
SSH鍵は、GitHubのリポジトリを選択 -> Settings(画面上) -> Secrets and variables(画面左) -> Actionsと辿って表示される画面で"New repository secret"をクリックすると登録することができます。
登録する際に、このSSH鍵に名前を付ける必要があります。今回はWEB_SSH_KEY
としました。
Deploy
SSH/SCPでdeployする際に、VPS上で以下を実行します。
- コンテンツが配置されているディレクトリ(以下、out)をアーカイブ(tar.gz)し、backupフォルダに移動する
- outを削除する
- GitHub Actionsでbuildしたコンテンツ(out.tar.gz)をSCPでサーバーに転送する
- 転送されたout.tar.gzを展開する
- nginxをreloadする
その処理を行うymlファイルは以下です。これを、リポジトリの.github/workflowディレクトリの下に任意の名前で配置します。
name: Deploy
on:
push:
branches:
- main
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install dependencies
run: npm install
- name: Build Next.js
run: npm run build && npm run export
- name: Archive the output folder
run: tar -czf out.tar.gz out
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: out-folder
path: out.tar.gz
deploy:
runs-on: ubuntu-latest
needs: build
steps:
- name: Download artifact
uses: actions/download-artifact@v4
with:
name: out-folder
- name: Set up SSH
uses: webfactory/ssh-agent@v0.9.0
with:
ssh-private-key: ${{ secrets.VPS_SSH_KEY }}
- name: Backup remote directory
run: |
ssh -o StrictHostKeyChecking=no user@your-vps-ip 'bash -s' << 'EOF'
BACKUP_DIR="/path/to/backup"
TARGET_DIR="/path/to/target-directory"
DATE=$(date +"%Y%m%d")
tar -czvf "$BACKUP_DIR/backup_$DATE.tar.gz" "$TARGET_DIR"
rm -rf "$TARGET_DIR"
echo "Backup completed: $BACKUP_DIR/backup_$DATE.tar.gz"
EOF
- name: Deploy to VPS using scp
run: |
scp -o StrictHostKeyChecking=no out.tar.gz user@your-vps-ip:/path/to/your/remote/directory
- name: Extract files on VPS
run: |
ssh -o StrictHostKeyChecking=no user@your-vps-ip "tar -xzf /path/to/your/remote/directory/out.tar.gz -C /path/to/your/remote/directory && rm /path/to/your/remote/directory/out.tar.gz && docker exec <container_name> nginx -s reload"
secrets.VPS_SSH_KEY
には、先ほど登録したSSH鍵に付けた名前を指定します。私の場合はsecrets.WEB_SSH_KEY
になります。 また、sshやscpのコマンドの/path/to/your/remote/directory
は、VPS上のパスに書き換える必要があります。
このファイルを加えてgit commit
->git push
すると、その後GitHub Actionsが実行され、VPSにbuildされたコンテンツがdeployされます。
おわりに
GitHub Actionsを使ってブログコンテンツをbuildし、deployしました。これでVultr VPSのspecを上げずに済みます😊