Next.js on GAEで失敗したデプロイ設定を供養する
うまくいったバージョンはこちら
Next.jsをGAEにデプロイするにあたり、 とある方法を取るとうまくいくはずなのに何故かうまくいきませんでした(未解決)。後から振り返られるように何をやったのかを載せておきます。
app.yamlの設定(ここは問題なし)
同じ内容のapp.yaml
でも他の方法だとうまく動いたので、おそらく失敗の原因ではないと思われます。
env: standard # スタンダード環境(省略可)
runtime: nodejs14 # Node.js 14を使う
instance_class: F4
service: default # GAEのサービスの名前。frontendとかでも良いかも
handlers:
- url: /_next/static
static_dir: .next/static
- url: /(.*\.(gif|png|jpg|ico|txt|svg))$
static_files: public/\1
upload: public/.*\.(gif|png|jpg|ico|txt|svg)$
- url: /.*
script: auto
secure: always
default_expiration: "12h" # 静的ファイルのキャッシュ期間
env_variables:
NODE_ENV: "production"
automatic_scaling:
min_instances: 0 # 動かしてないときはインスタンスを0にする
package.json
{
"scripts": {
"dev": "next dev",
+ "build": "next build",
+ "gcp-build": "npm run build",
+ "start": "next start -p $PORT",
},
}
解説1:パッケージのインストールはGAE側でやってくれる
GAEへデプロイする際にはgcloud app deploy
というコマンドを実行することになります。ここがすごく分かりづらいのですが、GAEスタンダード環境でNode.jsランタイムを使った場合、デプロイ時にGAE側でパッケージのインストールを行なってくれます。
アプリをデプロイすると、Node.js ランタイムは、npm install コマンドを使用して、すべての dependencies を自動的にインストールします(yarn.lock ファイルが存在する場合は yarn install コマンドを使用します)。
依存関係の指定
つまり、デプロイを行う際にはnpm install
コマンドを実行するステップは不要なはずです。
yarn install
になる
yarn.lockがあれば上に書かれている通り、プロジェクト内にyarn.lock
があればnpm install
の代わりにyarn install
を実行してくれます。
npm run build
は自動ではされないのでgcp-build
として指定
解説2: ただし、GAE側ではデプロイ時にnpm run build
の実行はしてくれません。そのままアプリを動かすと以下のようなエラーが発生します。
Error: Could not find a production build in the '/workspace/.next' directory. Try building your app with 'next build' before starting the production server.
GAEではpackage.jsonの
のscripts
にgcp-build
が含まれていると、そちらをビルド時に合わせて実行してくれるので"gcp-build": "npm run build"
を追記しておきます。
npm start
はGAEで実行される
解説3: Next.jsでビルドしたアプリを動かすにはnext start
を実行することになります。GAEではpackage.json
にstart
スクリプトが書かれていると、アプリ起動時に実行してくれます。
デフォルトでは、ランタイムは node server.js を実行してアプリケーションを起動します。package.json ファイルで start スクリプトを指定すると、ランタイムは代わりに指定された起動スクリプトを実行します。
アプリケーションの起動
.gcloudignore
の設定
.gcloudignore
.gitignore
node_modules/
ビルド後のソースコードをgcloud app deploy
にアップロードするのであれば.gcloudignore
にビルド前のファイル(/components
、/pages
、その他のソースファイル)も含めることができます。
しかし、今回のケースだとNext.jsのビルドはGAE側で行われるため、それらのファイルを.gcloudignore
に含めるとビルドに失敗します。
これでデプロイするとなぜか静的ファイルが読み込まれない
gcloud app deploy app.yaml --project=プロジェクト名
で、これでデプロイをしたところ、デプロイ自体は成功したのですが、なぜか静的ファイル(JS、CSSなどの.next/static
に吐き出されるファイル)が404になり、全くスタイルがあたらない状態になってしまいました。
何が原因なのかは分かってません
分からんのでクローズ