Next.JSをAzureのWeb App Serviceにデプロイする
最近、新しいアプリを作ってみたらデプロイに苦労したのでメモを残しておく。 2023.9.13時点で、Next.JSのアプリは、VSCodeの拡張機能や、Web App Serviceから自動設定できるGitHub連携のデフォルトのGitHub Actionでは、Next.JSのデプロイに時間がかかりすぎたり、うまくデプロイできないといった問題が生じている。原因としては、非常に膨大なファイル数をアップロード/デプロイしているからの様子。例えばnode_modules以下のファイル群など。
対策としては、Next.JSをStandaloneモードでビルドし、必要最小限のファイルに絞ってデプロイすればよいのだが、ビルドにいろいろ手を加える必要がある。
Standaloneモードでビルドするには、next.config.jsのoutputにstandaloneを設定すればよい。またdistDirでビルド結果の出力先を指定しておくほうが、デプロイに必要なファイルを集めやすかった。そのため、buildに出力するとする。
/** @type {import('next').NextConfig} */ const nextConfig = { distDir: 'build', output: 'standalone', } module.exports = nextConfig
次に、package.jsonのscriptにpostbuildを追加する。postbuildはbuild終了時に実行したいコマンドを定義することができる。Next.JSではCDEに配置すべきファイルということでビルド時にいくつかのファイルは分けられているらしい。CDEを活用する場合は違った設定を考えたほうが良いのだろう。(ここではそこまで考えない)
また、実行時に不要なモジュールはdevDependenciesへ変更している。
{ "name": "next-app", "version": "0.1.0", "private": true, "scripts": { "dev": "next dev", "build": "next build", "postbuild": "cp -r public build/standalone && mkdir -p build/standalone/public/_next && cp -r build/static build/standalone/public/_next/", "start": "next start", "lint": "next lint" }, "dependencies": { "next": "13.4.19", "react": "18.2.0", "react-dom": "18.2.0" }, "devDependencies": { "@types/node": "20.6.0", "@types/react": "18.2.21", "@types/react-dom": "18.2.7", "eslint": "8.49.0", "eslint-config-next": "13.4.19", "typescript": "5.2.2" } }
最後に、GitHub Actionsのymlファイルを以下のように直す。
# Docs for the Azure Web Apps Deploy action: https://github.com/Azure/webapps-deploy # More GitHub Actions for Azure: https://github.com/Azure/actions name: Build and deploy Node.js app to Azure Web App - next-sample-app on: push: branches: - main workflow_dispatch: jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Set up Node.js version uses: actions/setup-node@v3 with: node-version: '20.x' - name: npm install, build, and test run: | npm install npm run build --if-present npm run test --if-present npm prune --production cd build/standalone zip -qr ../../package.zip . cd ../../ env: DATABASE_URL: ${{ secrets.AZURE_DATABASE_URL }} - name: Upload artifact for deployment job uses: actions/upload-artifact@v3 with: name: node-app path: package.zip - name: Clean run: | rm -rf build rm -rf package.zip deploy: runs-on: ubuntu-latest needs: build environment: name: 'Production' url: ${{ steps.deploy-to-webapp.outputs.webapp-url }} steps: - name: Download artifact from build job uses: actions/download-artifact@v3 with: name: node-app - name: 'Deploy to Azure Web App' id: deploy-to-webapp uses: azure/webapps-deploy@v2 with: app-name: 'next-sample-app' slot-name: 'Production' publish-profile: ${{ secrets.XXXX }} package: package.zip
ポイントだけ説明する。
buildすると、build/standaloneフォルダに必要なファイル一式がそろうようにしている。(postbuildで必要なファイルのコピーを追加したため。) それをpackage.zipに圧縮している。
cd build/standalone zip -qr ../../package.zip . cd ../../
アップロード/ダウンロード時間を軽減にはかなり効く。実際速くなっている。
本記事では、AzureのWeb App Serviceのデプロイを対象に説明したが、少しアレンジすれば、ほかの環境へのデプロイでも参考になるのではないかとは思う。
以上。
2023/10/29追記
スタンドアローンモードでビルド、実行するため、Web App Serviceのスタートアップコマンドは以下に変更する必要があった。
node server.js
Web App Serviceの場合、Webの管理画面から、「設定 > 構成 > 全般設定 > スタートアップ」で設定する必要があった。 変更していないままデプロイするとコマンドが見つからずエラーが起きる。
2024/2/10追記
Next.JSのデフォルトポートは3000だが、Web App Serviceのデフォルトは8080なので、対応させる必要がある。 これは「構成」からアプリケーション設定にPORTを3000として追加するだけでよい。