Rails：①アセットパイプライン？ビルドツール？ 何それ（アセットパイプラインについて）

## 背景

Railsフロントを扱おうと思うと色々な単語が飛び交います。

  - アセットパイプラインって何？
  - Webpacker？Sprockets？わけわからん
  - Esbuildがおすすめ？
  - じゃあyarnって何で必要なの？

自分が日々の業務で疑問に思っていることをまとめていきます

## 用語の整理

最初に、用語の整理をします。

何言ってんのかわからない状態を脱するため、とりあえず、聞いたことがるがわからん単語を洗い出してみました。

- アセットパイプライン
- アセット
- `Webpacker`
- `Webpack`
- `Esbuild`
- `Babel`
- ビルド
- ビルドツール
- コンパイル
- `Sprockets`
- `yarn`
- `npm`
- `Node`
- `node_modules`
- `assets:precompile`コマンド
- `import-map`

ざっくりこんな感じでした
流石にこれはわかるだろうと言うものもありますが一旦挙げます。

次にこれを分類してみます。もちろんAIの力を借りて

### 分類した単語たち

#### アセットパイプライン関連
- アセットパイプライン
- アセット
- `Sprockets`
- `assets:precompile`コマンド
- `import-map`

#### ビルドツール関連
- `Webpacker`
- `Webpack`
- `Esbuild`
- `Babel`
- ビルド
- ビルドツール
- コンパイル

#### パッケージマネージャー関連
- `yarn`
- `npm`

#### Node.js関連
- `Node`
- `node_modules`

大きく4つに分けてくれましたので、上から調査していきます

## アセットパイプライン関連

### アセットパイプラインとは

「JavaScript」「CSS」「画像」のことを**アセット**といいます

WebサイトはHTML+アセット群で構成されているので、色々な装飾やアニメーション、画像などが表示されます

そのアセットを効率よく閲覧者に配信するための仕組みを**アセットパイプライン**といいます

そしてこのアセットパイプラインを提供しているのが`Sprockets`です(Rails6系では)

ただし現在は下記のような構成になっています（2025/01/22）

- Rails7より前は`Sprockets`がデフォルトで使用されていました（Rails6系とか）
- Rails7以降は`Webpacker`や`importmap`が推奨されています（Rails7系）
- Rails7以降は`Webpacker`は推奨されなくなりました、その代わりに`Esbuild`とかを使う（Rails7.1くらいから）

※ `Webpacker`と`importmap`、`Esbuild`についてはまた後ほど解説

アセットパイプラインは主に4つの機能を提供してくれています

- アセットの連結
- アセットのコンパイル
- アセットの圧縮
- フィンガープリントの追加

#### アセットの連結

アセットの連結とは、それぞれ複数のcssファイル、jsファイルを1つのcssファイル、jsファイルにしてまとめてしまう機能のことを言います

具体的に何が便利なのか…

例えば、ユーザーがあるサイトがみたい！とサーバーにリクエストを送ります。

サーバーは要望通りHTMLファイルをユーザーに送ります。

するとHTMLファイルの中には下記のようなコードが含まれていました

```HTML
<link rel="stylesheet" href="">
<script src=""></script>
```

言わずもがな、HTMLの中で`css`や`js`を呼び出しているコードになります。

よって再度`css`ファイル`js`ファイルをくださいとリクエストを送ります。

ペラ１のサイトであればこれで`css`や`js`を一回送信すれば終わりですが、

例えばこれが複数のファイルだった場合は、いちいちサーバーに「`CSS`ファイルくーださい！」「`JS`ファイルくーださい！」と伝えると、通信速度がめっちゃ遅くなってしまいます。

なので「複数のファイルをまとめて連結しようぜ」となります。それがアセットの連結です。

#### アセットのコンパイル

正確にいうと「高級言語のコンパイル」になります

- **コンパイル**とは、我々が記述したプログラミング言語をコンピュータが理解しやすい形に変更する作業です

- **高級言語**とは、我々がより理解しやすい形式になったプログラミング言語です
  
`CSS`における`SCSS`、`JS`における`TypeScript`や`CoffeeScript`のことです

アセットパイプラインはこういった高級言語をコンパイルして、ブラウザが認識できる形に翻訳をしてくれています。

#### アセットの圧縮

'CSS'や'JS'ファイルの不要な空白、改行、コメントアウトなどを取り除く作業を言います。

人間にとっては空白や改行、コメントアウトはコードを見やすくするために必要な工程ですが、ブラウザにとっては不要です。

余計な部分を削ぎ落としてファイルを軽くして、読み込み速度を上げてくれます。

#### フィンガープリントの追加

フィンガープリントとは、キャッシュを破棄するのか、しないのかの指標となる機能です。

どういうことなのか…

そもそもキャッシュとは、一度閲覧したWebページの情報を一時的に保存しておく仕組みのことを言います。

先ほども説明した通り、WebページはHTMLの他にも「JavaScript」「CSS」「画像」からなるアセットで構成されています。
そして、ユーザーはサーバーに対して「アセットちょーだい！」とリクエストを送ってWebサイトをブラウザで閲覧しています。

キャッシュが一度ブラウザの情報を保存してしまえば、ユーザーが同じWebサイトにアクセスするときにサーバーにいちいちリクエストを送る必要はありません。
ブラウザは一度ダウンロードしたアセットを再利用して、ページの読み込み速度を向上させることができます。

しかし、アセットが更新された場合、古いキャッシュが残っていると最新のアセットが反映されません。

これを防ぐために、フィンガープリントが登場します。

フィンガープリントは、アセットのファイル名にハッシュ値を追加することで実現されます。

例えば、`application.css`というファイルがあるとします。これにフィンガープリントを追加すると、`application-abc123.css`のようになります。このハッシュ値はファイルの内容に基づいて生成されるため、ファイルが変更されるとハッシュ値も変わります。

これにより、ブラウザは新しいハッシュ値を持つファイルをダウンロードし、最新のアセットを取得することができます。結果として、ユーザーは常に最新のアセットを閲覧できるようになります。

### Sprockets

先ほどちょっとだけ登場した`Sprockets`についてです

`Sprockets`とはRails3.1~7.2くらいまでアセットパイプラインとして使用されていたらしいです（長いすねRailsの歴史）

Rails7からは`importmap`なるものが出たらしく、JS用のアセットパイプラインは`importmap`、CSS用のアセットパイプラインは`Sprockets`となっています

Rails8からは`Sprockets`から`Propshaft`に変更されています

## 感想

- アセットパイプラインってなんだよと思ってましたが、意外と調べてみるとわかりやすかった
- ビルドツールや`Webpacker`とは何が違うのか気になる

## 参考

https://qiita.com/junya__ya/items/6d768e9873eab9015e7d

https://railsguides.jp/v6.1/asset_pipeline.html