Rails(turbolinks)でページの初回読み込みがうまくいかない時に考えること

# 初投稿
初投稿になりますのでお手柔らかによろしくお願いします。

# 環境
Ruby 2.6.5
Rails 6.0.3.2

# 概要
Railsでのアプリケーション作成においてページ遷移した際に挙動がうまくいかないことがありました。

私自身、結構詰まってしまった箇所なので備忘録として残しておきます。
また同じように詰まってしまった人へ少しでもgiveできれば良いなと思っています。

# 達成したいゴール
ページの初回読み込みがうまくいかない人へ1つのヒントとなるような情報を提示すること。
turbolinksを使用している際にページの読み込みを考える。

# 解決したい問題
Railsのturbolinksを使用している際にページの初回読み込みがうまくいかないこと。

# turbolinksとは
・turbolinksとはRails4.0からデフォルトで導入されたgem
・turbolinksとは画面遷移を高速化させるライブラリ（画面全体を更新するのではなく、画面の一部だけを更新する）
・turbolinksが原因でJavaScriptが上手く機能しなくなる場合がある

# turbolinksを使ったページ遷移の流れ
①ページのHTMLが読み込まれる
②ページの中で参照されているCSS、JavaScriptを読み込む
③ページをレンダリング（情報を元にページを表示）

この②の段階で複数のCSS、JSファイルが存在すると、ブラウザとWebサーバの間で複数の通信が行われてしまい、通信速度が遅くなってしまいます。

そこで「asset pipeline」というフレームワークが登場しました（Rails3.0から）。
アセットパイプラインとは、Ruby on Railsのアプリケーション内で使用したいJavaScriptやCSS、画像ファイルを「開発作業がしやすいようにしつつ、最終的に一つのファイルに連結・圧縮する」仕組みのことです。

このアセットパイプラインによりブラウザとサーバ間の通信が抑えられました。

そして、Rails4.0からアセットパイプラインに新たに追加されたのが「turboliks」です。

「turbolinks」は、ページ遷移をする際に、現在のページの「title」と「body」だけを抜き取って、新しいHTMLの「title」と「body」に変換します。
これにより、CSSやJavaScriptをブラウザが取得し直す処理がなくなり、処理速度が速くなります。

# turbolinksの注意点
turbolinksを使用すると、ページ読み込みを起点としたJavaScriptは機能しなくなってしまいます。

通常であればページが読み込まれたタイミングでloadイベントが発生します。
しかし、turbolinksによって画面が切り替わった場合はloadイベントが発生されません。

# 解決策

そのため、下記の記述で初回読み込み、リロード、ページ切り替えで動くようにします（第一選択）。

```js
$(document).on('turbolinks:load', ()=> {
```
例を見てみましょう。

```js
$(document).on('turbolinks:load', ()=> {
  $('#image-box').on('change', '.js-file', function(e) {
    // thisがconpilationクラスを持っているかhasClassメソッドで判定
    const conpilation = $(this).hasClass('conpilation');
    if (!conpilation) {
      // fileIndexの先頭の数字を使ってinputを作る(.appendは要素内の末尾にタグを追加する)
      $('#image-box').append(buildFileField(fileIndex[0]));
      // ここの`item_images_attributes_${fileIndex[0]}_image`)とconst htmlのid="item_images_attributes_${index}_image">が一緒になればOK
      $('.ListingMain__entire__menu__list__field__display__content').attr('for', `item_images_attributes_${fileIndex[0]}_image`)
      // shift()メソッドは配列から最初の要素を削除して、その要素を返す。このメソッドは配列のlengthを変更する。
      fileIndex.shift();
      // 末尾の数に1足した数を追加する(.pushは配列の末尾に新しい要素を追加するためのメソッド)
      fileIndex.push(fileIndex[fileIndex.length - 1] + 1);
    } else {
      return false;
    }
  });
});
```
これで上手くいくはず！！！っと思いましたが、初回読み込み時のみ挙動がおかしくなってしまいます。

### 第二選択
画面の読み込み時に発火するようにしてみます。

```js

$(document).on('ready page:load', ()=> {
```
しかし、これでも上手くいきません。。

### 第三選択
これでダメであればどうしようもありません。

```ruby
= link_to new_item_path, class: "Sell__listing", data: {"turbolinks" => false} do
```
結論として、上記の記載でページの初回読み込み時に上手く動くようになりました。

```ruby
data: {"turbolinks" => false}
```
この記載がポイントです。
これで遷移先のページのみturbolinksを切ることが出来ます。

# 補足
Rails6.0以降のバージョンからは、WebpackerというGemが標準で導入されています。
Webpackとは、Webアプリケーションを作成する際に必要なさまざまなJavaScriptをひとまとめに管理するためのフレームワークです。
モダンなWebアプリケーション開発では、さまざまなJavaSctiptライブラリを用いるため、その依存関係を管理してくれます（モジュールバンドラ）。

### Webpacker
これまでのRailsでは、JavaScript等を管理するために、アセットパイプラインを使用していました。
しかし、JavaScriptのライブラリが充実してきたため、Rails6.0以降からはWebpackを利用する方針へ転換されつつあります。

今回は、jQueryを使用したためアセットパイプラインでの実装で問題はありませんでした。
今後は、Webpackerを使用することがあるかもしれません。
ですが、Webpackerを使用しなくても、WebpackはRailsアプリケーションに導入することができるそうです。
この辺りはまだまだ勉強不足のためこれから学習を進めていこうと思っています。

# まとめ
Rails4.0以降を使用していて、ページの読み込みが上手くいかない時は上記のことを考えてみると上手く実装できるかもしれません。

参考:
https://qiita.com/hiroyayamamo/items/b258acbaa089d9482c8a
https://www.ryotaku.com/entry/2019/01/15/213420

# 終わりに
この記事がお役に立てる内容になっていると幸いです。
これから、少しでもgiveできるように自分が学んだことを発信していければ良いなと思っています。
よろしくお願いします。