Laravel mixのアセットがherokuで動かない時の対処法
技術スタック JavascriptwebpackLaravelインフラ

Laravel mixのアセットがherokuで動かない時の対処法

2021.05.04 2021.03.27

こんにちはjunです。最近よくLaravelの開発を行っていて、プロトタイプとかをherokuにあげるのですがLaravel mixのアセットが動かない(main.jsが404)でちょっと困ったので、今回はその対処法を書きたいと思います。

Laravelmixの説明を軽くするので、さっさと解決策みたいひとは「ビルドアセットをgitignoreしていた」から参照してください。なお使用環境は以下の通りです。

Laravel 6 PHP 7.4 Node.js 12.21(開発) Node.js 14.16(heroku)

Laravel Mixって?

Laravel MixはLaravelが公式に出している、JS・CSSのアセットコンパイラとモジュールバンドラです。resource配下のjsやsassをコンパイルしたり、バンドルするwebpackの設定がすでにLaraveに最適化されています。webpackをほとんど触らずともvue、react、sass、そのほかjsライブラリをもちいた開発ができます。

resource 配下のアセットはLaravel Mixによってpublic配下に自動的に吐かれるようになっています。開発時にはnpm run watchをしていますが、よく見るとpublic配下に開発用ビルドしたアセットファイルが逐一置かれています。

大体のLaraveフロントエンドではこのMixを用いて開発していることが多いと思います。しかしherokuや本番環境にあげた時にちょっと問題がおきました。

main.js is not found

Laravel Mixでフロントを構築して、ある程度バック含めて完成したのでherokuにデプロイしてみました。ビルドは普通に成功し、満を辞して目的の画面をみてもmain.js is not foundとなってしましました。main.jsにはビルドしたvue.jsのプロジェクトがあるはずなのにと思い、サーバーに入ってpublic/js配下をみてみたところ、何もありませんでした。

原因その1:ビルドアセットをgitignoreしていた

ビルドされたアセットはpublic配下に置かれますが、ファイル量が膨大だったり、開発モードと本番モードが混じる可能性があること、あとどうせコロコロ変わるのでバージョン管理から外そうと思い、public/jsとpublic/cssはバージョン管理から外していました。

herokuは基本的にgitを用いてデプロイします。管理対象外のファイルはもちろんherokuサーバー上にないので、アセットがあるはずもありません。であればherokuにデプロイした時にLaravel Mixを叩いて、ビルドすれば解決します。

原因その2:Laravel MixがdevDependencies

HerokuではNODE_ENVproduction(本番環境)で定義されていると、devDependenciesがプリーニングされてしまい、ビルドがうまく走りません。

デフォルトでは、Heroku は ​package.json​ の ​dependencies​ および ​devDependencies​ に記載されているすべての依存関係をインストールします。

インストールおよび​ビルドステップ​を実行した後、 Heroku はアプリケーションをデプロイする前に、​devDependencies​ に宣言されているパッケージを取り除きます。

https://devcenter.heroku.com/ja/articles/nodejs-support#skip-pruning

インストールおよび​ビルドステップ​を実行した後、 Heroku はアプリケーションをデプロイする前に、​devDependencies​ に宣言されているパッケージを取り除きます。

対策としてはpackage.jsonをいじってdependenciesに移動します。デフォルトでLaravel Mixはdevの方にインストールされます。それを移動してプッシュすればひとまずLaravel Mixのビルドがうまくいきます。

原因その3:npm run productionを動かすように設定

その2に加えて、今度はherokuデプロイの際にLaravel Mixのビルドスクリプトがキックされるように設定します。herokuはNode.jsのプロジェクトがあり、そのスクリプトにnpm run buildがある場合はそれを実行してくれます。

初期のpackage.jsonのスクリプトはbuildがないので、mixが実行されません。

pakage.json
"scripts": {
    "dev": "npm run development",
    "development": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --config=node_modules/laravel-mix/setup/webpack.config.js",
    "watch": "npm run development -- --watch",
    "watch-poll": "npm run watch -- --watch-poll",
    "hot": "cross-env NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --disable-host-check --config=node_modules/laravel-mix/setup/webpack.config.js",
    "prod": "npm run production",
    "production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --no-progress --config=node_modules/laravel-mix/setup/webpack.config.js"
},

ちょうどprodというのがあるのでbuildに変えてやりましょう。

pakage.json
"scripts": {
    "dev": "npm run development",
    "development": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --config=node_modules/laravel-mix/setup/webpack.config.js",
    "watch": "npm run development -- --watch",
    "watch-poll": "npm run watch -- --watch-poll",
    "hot": "cross-env NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --disable-host-check --config=node_modules/laravel-mix/setup/webpack.config.js",
    "build": "npm run production",
    "production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --no-progress --config=node_modules/laravel-mix/setup/webpack.config.js"
},

こうすればnpm run buildnpm run production を実行して本番用のアセットを作ってくれます。これで解決です。

ビルドアセットがうまく出力されない時に考えるべきこと

今回はいくつかのファイルをビルドする必要があり、デプロイ作業が自動で行われる状況でした。開発環境ではアセットがあるのに、本番だとなくなっているという場合は以下のことを考えましょう。

  • ファイルはある?(サーバーに入ってlsしてチェック)
  • ビルドに必要なモジュールがインストールされているか?
  • ビルドスクリプトはキックされているか?

大体こうゆうときはビルドがうまくいっていないので、そこからチェックしていくといいです。ちなみに私が検索した時のワードは 「heroku laravel mix ビルド」 でした。それではまた。

Copyright © 2021 jun. All rights reserved.