【Rails7+esbuild】デプロイ時にasset pipeline系のエラーが出たら確認すること

# デプロイしたらエラー出るよね！知ってた！😇

下記記事を書いて意気揚々とデプロイしたら```ActionView::Template::Error (The asset "●●.js" is not present in the asset pipeline.)```で苦しめられました。

https://qiita.com/MIDO-ruby7/items/9f28475174a3c9d5f5d1

今回のケースはJSファイルですが、デプロイ後に画像やcssが適用されない方も本記事が参考になれば幸いです。

## 👀そもそも理解しておいた方が良いこと
### ブラウザがどこを読み取っているか。
#### → /public/assetsにプリコンパイルされたファイルを読み取っている🔥
これが超重要です。つまりここにファイルが無い=```ActionView::Template::Error```や画像が読み込めないことにつながります。


## /public/assetsをherokuアプリ上で確認する
目的のファイルが/public/assetsに存在するのかを確認してみましょう。

まずは自分のherokuアプリ上に入ります。
ローカルで下記コマンドを実行
```
$ heroku run bash
```
すると、herokuアプリのbashとつながります。
初学者(俺)向けなのであえて書くと、アプリのターミナルと繋がったと思ってください。

次に/public/assetsの中身を確認します。
```
~$ ls -la public/assets
drwx------ 2 u数字 dyno   12288 Aug 24 20:59 .
drwx------ 3 u数字 dyno    4096 Aug 24 20:59 ..
-rw------- 1 u数字 dyno   15699 May 27 00:52 actioncable-543なんか文字列いっぱいよ0107cbc9a1aa0c838d9a74e.js
-rw------- 1 u数字 dyno    3707 May 27 00:52 actioncable-54334なんか文字列いっぱいよ0107cbc9a1aa0c838d9a74e.js.gz
-rw------- 1 u数字 dyno   14080 May 27 00:52 actioncable.esm-e01089cなんか文字列いっぱいよba7537f70690.js
以下略
```
少し変な名前のファイルが並びますが、例えばapplication.jsも本番環境では```application-<fingerprint>.js```という形にファイル名が変わります。fingerprintのところに16バイトのランダムな16進文字列が入るらしいです。
詳しくはRailsガイドをどうぞ

https://railsguides.jp/asset_pipeline.html#%E3%82%A2%E3%82%BB%E3%83%83%E3%83%88%E3%82%92%E3%83%97%E3%83%AA%E3%82%B3%E3%83%B3%E3%83%91%E3%82%A4%E3%83%AB%E3%81%99%E3%82%8B


public/assets内には.jsファイルだけでなく、.pngなどの画像やCSSも入っているはずです。
##### public/assets内に目当てのファイルがなければ、それは"プリコンパイル"がうまくいっていないということです。

## public/assetsにプリコンパイルさせるには
「これをプリコンパイルしてよ」とプリコンパイル対象を指示する必要があります。
その設定をするのが、config/initializers/assets.rbです。


ただ、assets.rbをいじる前にまずは該当のファイルがプリコンパイル対象に含まれているかを確かめます。

herokuのbashに入ったまま

```
~$ rails c
```
コンソールが立ち上がったら、

```
[1] pry(main)> Rails.application.config.assets.precompile
"manifest.js",
 "turbo.js",
 "turbo.min.js",
 "turbo.min.js.map",
略
```
##### 表示されたファイルの中に目的のファイルがあるか確かめてください。
ただ、私はapplication.jsやapplication.cssは表示されませんでした。デフォルトの読み込み設定は表示しないのかもしれないです。デフォルトでプリコンパイル対象となるのは、app/assets以下のファイルだそうです。

と言うことで、次にapp/assetsに何が入っているかも確認しましょう。
```
assets                          
├─ builds                                 
├─ config                                    
├─ images                                      
└─ stylesheets            
```

.jsファイルはapp/javascriptにあるから、そもそもapp/assetsには無いのでは？疑問に思うかもしれませんが（私は混乱した）、実はapp/assets/buildsにあります。

```
assets                          
├─ builds                 #この中にあるはずなんやで            
│  ├─ add_jquery.js             
│  ├─ add_jquery.js.map         
│  ├─ application.css           
│  ├─ application.js    　 
│  ├─ application.js.map                 
│  ├─ top_bubble.js             
│  ├─ top_bubble.js.map               
├─ config                       
│  └─ manifest.js               
├─ images                       
│  ├─ favicon.png               
│  ├─ icon180.png               
│  ├─ icon192.png                              
│  ├─ logo2.png                         
│  └─ ogp.jpg                   
└─ stylesheets                  
   ├─ actiontext.css            
   ├─ application.tailwind.css  
   ├─ bubble.css                
   ├─ top.css                   
   ├─ top_bubble.css            
   └─ wave.css                  
```
もしbuildの中になければ、そもそもコンパイルがうまくいっていない可能性が高いです。こちらについては後ほど説明を書きたいと思います。

今はこのapp/assets/builds内に目的のファイルがあると仮定します。(cssや画像の場合はimagesやstyleseetsに入ってればOK)

★app/assets/builds以下に目的のファイルがある⭕️
★コンソールで確認した```Rails.application.config.assets.precompile```で出てきたファイルには存在しない
時は目的のファイルがプリコンパイルの対象になっていない可能性が高いです。

##### 結論としては、下記のように書くことでプリコンパイル対象を設定できました。
```config/initializers/assets.rb
# Be sure to restart your server when you modify this file.

# Version of your assets, change this if you want to expire all your assets.
Rails.application.config.assets.version = '1.0'

# Add additional assets to the asset load path.
# Rails.application.config.assets.paths << Emoji.images_path

# Precompile additional assets.
# application.js, application.css, and all non-JS/CSS in the app/assets
# folder are already added.
# Rails.application.config.assets.precompile += %w( admin.js admin.css )

#ここを追加。書き方は色々ある模様
Rails.application.config.assets.precompile += %w(
  custom/bubble.js
  custom/default_values.js
  custom/preview.js
  custom/search.js
  custom/top_bubble.js
  custom/tourguide.js
)
```

え〜と、私も混乱してきました。整理しましょう。

例えば、top_bubble.jsでエラーが出ているとします。
①app/javascript/top_bubble.jsがあなたがコードを書いたファイルです。
②esbuildはこれをOSが読み取れる形に"コンパイル"します。その結果がapp/assets/builds/top_bubble.jsに格納されています。
③さらに本番環境ではブラウザが読み取れる形に"プリコンパイル"されます。それが最初に確認した/public/assets/top_bubble.esm-e01089csger444525ba7537f70690.jsみたいなやつです(数字は適当です)

ここまでは、"プリコンパイル"がうまくできていないことが原因だと考え、assets.rbにtop_bubble.jsをプリコンパイル対象にするよう設定した作業になります。

## app/assets/builds内に目的のファイルが無い時

★app/assets/builds以下に目的のファイルがない❌
★コンソールで確認した```Rails.application.config.assets.precompile```で出てきたファイルにも存在しない

##### "コンパイル"がうまくいっていない。

これについては下記に書いたのでご覧ください。

https://qiita.com/MIDO-ruby7/items/9f28475174a3c9d5f5d1#3appassetsbuilds%E3%81%AB%E5%80%8B%E5%88%A5%E3%81%AB%E8%AA%AD%E3%81%BF%E8%BE%BC%E3%81%BF%E3%81%9F%E3%81%84js%E3%81%8Cbuild%E3%81%95%E3%82%8C%E3%81%A6%E3%81%84%E3%82%8B%E3%81%8B-1

加えて、herokuの場合は設定したコマンドをデプロイ時に実行させる必要があります。
```package.json
"scripts": {
    "start": "bin/rails server -p $PORT -e production",
    "build": "esbuild app/javascript/*.* --bundle --sourcemap --outdir=app/assets/builds --public-path=assets",
    "build:css": "tailwindcss -i ./app/assets/stylesheets/application.tailwind.css -o ./app/assets/builds/application.css --minify",
    "build:custom": "esbuild app/javascript/custom/*.js --bundle --sourcemap --outdir=app/assets/builds --public-path=assets",
    "heroku-postbuild": "yarn run build && yarn run build:custom"
  }
```
``` "start": "bin/rails server -p $PORT -e production"```と
```""heroku-postbuild": "yarn run build && yarn run build:custom"```
の部分を追加しました。
```"heroku-postbuild"```を設定すると```"build"```が実行されなくなるので```"build"```と```"build:custom"```両方を実行してあげる必要があります。
（npmの場合はChatGPTに聞いてください。試してないのでわかりません😇）

"heroku-postbuild"を実行させるにはherokuのプラグインが必要です。

https://elements.heroku.com/buildpacks/heroku/heroku-buildpack-nodejs

```.ターミナル
$ heroku buildpacks #buildpacksの確認

=== boozefolio Buildpack URL
heroku/ruby　#rubyしかない
```
 heroku/nodejsのbuildpacksは無いようなので、インストールします。
```.ターミナル
$ heroku buildpacks:add heroku/nodejs
›   Warning: heroku update available from 7.68.2 to 8.1.9.
Buildpack added. Next release on boozefolio will use:
  1. heroku/ruby
  2. heroku/nodejs
Run git push heroku main to create a new release using these buildpacks
```

このファイルをデプロイするとビルドされていると思います。それでもエラーが出る場合は、/public/assetsをherokuアプリ上で確認するから順番に確認してみてください。

また、エラーが画像の場合は下の神記事にもお世話になりました。

https://qiita.com/jnchito/items/3d225112a3ac95379b1d

特に検索するとよく出てくる方法が間違っている方法だと解説されているのが今回の場合でもとても助かりました。
> 🚨これは間違い！！
```config/environments/production.rb```を開き、 ```config.assets.compile = false``` の値を ```true``` に変更しましょう。

また、下記記事の丁寧な解説のおかげで今回エラーを解決できました。ありがとうございました。

https://qiita.com/metheglin/items/c5c756246b7afbd34ae2

### 参考文献

https://railsguides.jp/asset_pipeline.html

https://blog.mothule.com/ruby/rails/ruby-rails-assets-pipeline-use