Rails アセットパイプラインとは
general to specific
そもそもなぜ静的ファイルだけ本番環境で取り扱いが違うのか?
Railsでは、Viewを構成するHTML以外の要素をアセット(Assets)と呼ぶ。具体的には、
CSSファイル
JavaScriptファイル
画像ファイル
を指す。
Railsではアセットを効率的に扱う仕組みがあり、「アセットパイプライン」と呼ばれる。アセットファイルを連結・圧縮することで、Railsアプリを高速化する。
アセットパイプラインを実現しているのがSprockets(一部でWebpacker)である。
ローカルでrails assets:precompileすると、デフォルトだとpublic/assets配下にビルドファイルが吐き出される。
code:zsh
❯ ls public/assets/
actioncable-da745289dc396d1588ddfd149d68bb8e519d9e7059903aa2bb98cfc57be6d66e.js
actioncable-da745289dc396d1588ddfd149d68bb8e519d9e7059903aa2bb98cfc57be6d66e.js.gz
actioncable.esm-3d92de0486af7257cac807acf379cea45baf450c201e71e3e84884c0e1b5ee15.js
actioncable.esm-3d92de0486af7257cac807acf379cea45baf450c201e71e3e84884c0e1b5ee15.js.gz
actiontext-2cbe83c53ac55751766b846f03c0f117d6f2a1b58bec8c45d05510b6d8d2ba13.js
actiontext-2cbe83c53ac55751766b846f03c0f117d6f2a1b58bec8c45d05510b6d8d2ba13.js.gz
activestorage-66f58884eeef2512d26d68339169134e187ee30b7c9a8bf787d54ba426f87f7b.js
activestorage-66f58884eeef2512d26d68339169134e187ee30b7c9a8bf787d54ba426f87f7b.js.gz
activestorage.esm-e6f556def16438cabebcb3b9e9fe903c4a78333331dc4bd9860f98ee6d050ba3.js
activestorage.esm-e6f556def16438cabebcb3b9e9fe903c4a78333331dc4bd9860f98ee6d050ba3.js.gz
application-37f365cbecf1fa2810a8303f4b6571676fa1f9c56c248528bc14ddb857531b95.js
application-37f365cbecf1fa2810a8303f4b6571676fa1f9c56c248528bc14ddb857531b95.js.gz
application-e0cf9d8fcb18bf7f909d8d91a5e78499f82ac29523d475bf3a9ab265d5e2b451.css
application-e0cf9d8fcb18bf7f909d8d91a5e78499f82ac29523d475bf3a9ab265d5e2b451.css.gz
controllers/
es-module-shims-9e0c70685497a549ab07a74fc9ec13c2f0cd4952ccf7570d08f29f43473ecb7d.js
es-module-shims-9e0c70685497a549ab07a74fc9ec13c2f0cd4952ccf7570d08f29f43473ecb7d.js.gz
es-module-shims.js-363f5d8dbcfc8948923497b4b8e3ce188d1704534aabd480a3c8a69700b7c983.map
es-module-shims.min-6982885c6ce151b17d1d2841985042ce58e1b94af5dc14ab8268b3d02e7de3d6.js
es-module-shims.min-6982885c6ce151b17d1d2841985042ce58e1b94af5dc14ab8268b3d02e7de3d6.js.gz
manifest-b84bfa46a33d7f0dc4d2e7b8889486c9a957a5e40713d58f54be71b66954a1ff.js
manifest-b84bfa46a33d7f0dc4d2e7b8889486c9a957a5e40713d58f54be71b66954a1ff.js.gz
stimulus-0ce1b26664523b4ad005eb6a6358abf11890dad17c46d207e5b61a04056d7b26.js
stimulus-0ce1b26664523b4ad005eb6a6358abf11890dad17c46d207e5b61a04056d7b26.js.gz
stimulus-autoloader-2c31fda20cec0bdbfa933e7f149712e27af6e6ac829d23f81975f6ebd4d830cf.js
stimulus-autoloader-2c31fda20cec0bdbfa933e7f149712e27af6e6ac829d23f81975f6ebd4d830cf.js.gz
stimulus-importmap-autoloader-b10ce93483412df368cf597e99e0d924a712f36e0910e674236239f6028ed0a8.js
stimulus-importmap-autoloader-b10ce93483412df368cf597e99e0d924a712f36e0910e674236239f6028ed0a8.js.gz
stimulus-loading-685d40a0b68f785d3cdbab1c0f3575320497462e335c4a63b8de40a355d883c0.js
stimulus-loading-685d40a0b68f785d3cdbab1c0f3575320497462e335c4a63b8de40a355d883c0.js.gz
stimulus.min-900648768bd96f3faeba359cf33c1bd01ca424ca4d2d05f36a5d8345112ae93c.js
stimulus.min-900648768bd96f3faeba359cf33c1bd01ca424ca4d2d05f36a5d8345112ae93c.js.gz
stimulus.min.js-5cdf38f474c7d64a568a43e5de78b4313515aa0e4bd3d13fac297fffeba809f0.map
trix-1563ff9c10f74e143b3ded40a8458497eaf2f87a648a5cbbfebdb7dec3447a5e.js
trix-1563ff9c10f74e143b3ded40a8458497eaf2f87a648a5cbbfebdb7dec3447a5e.js.gz
trix-ac629f94e04ee467ab73298a3496a4dfa33ca26a132f624dd5475381bc27bdc8.css
trix-ac629f94e04ee467ab73298a3496a4dfa33ca26a132f624dd5475381bc27bdc8.css.gz
turbo-7b0aa11f61631e9e535944fe9c3eaa4186c9df9d6c9d8b1d16a1ed3d85064cf0.js
turbo-7b0aa11f61631e9e535944fe9c3eaa4186c9df9d6c9d8b1d16a1ed3d85064cf0.js.gz
turbo.min-96cbf52c71021ba210235aaeec4720012d2c1df7d2dab3770cfa49eea3bb09da.js
turbo.min-96cbf52c71021ba210235aaeec4720012d2c1df7d2dab3770cfa49eea3bb09da.js.gz
turbo.min.js-2e71e75cec6429b11d9575a009df6f148e9c52fbae30baf2292ec44620163b6f.map
ではなぜ最初から/public/assetsにファイルを置かないのか?それは、Minify、Compile、Fingerprintをする必要があるからである。
Minify(圧縮)とは?
コードを圧縮してファイルサイズを小さくすること。開発環境では、人間がコードを理解しやすいようにインデントやスペースがある。場合によってはコメントが存在する。
しかし本番環境でただ動かすだけなら、コードが人間にとって理解しやすい必要はない。インデント・スペース・コメント・空行を削除してファイルサイズを圧縮することをMinifyと呼ぶ。
Minifyするメリットは?
ファイルサイズを小さくできる→ つまり? → クライアントで負荷が減る→つまり?
具体的に圧縮されたコードを見るには?
実際圧縮したらパフォーマンスはどのくらい変わるの?
What is Compile?
言語を変換すること。
アセットパイプラインの文脈では、
SCSS/SASS→CSS
CoffeScript→JavaScript
などをする。ブラウザが解釈できるようにするため。
ただし、Webpackerが登場してからはJavaScriptのコンパイルはWebpackerが行っている。
What is Fingerprint?
headers.css => headers-XXXXXXXXXXXX.css
why would we want that? -> invalidate browser cache
どうキャッシュ対策になる?
→ ファイル名が変わることで以前のキャッシュファイルを使わずに新たなファイルを読み込む、ってこと?
ブラウザの予期せぬキャッシュを回避するためで、コード修正時に毎回ダイジェスト値が変わることによりキャッシュを回避できます。
in development environment
compile on every request
minify is off -> so you can debug
fingerprint is off
in production environment
compile once at deploy
minify is on
fingerprint is on
圧縮、連結、フィンガープリントはRailsでのアプリケーション開発に限ったことではなく、ウェブアプリケーション開発全体で一般的なこと。
アセットファイルを連結する仕組み
マニフェストファイルと呼ばれる、すべてのファイルの起点となるファイルに連結対象のファイルを記述する。
マニフェストファイル:
JavaScriptの場合:app/javascript/packs/application.js
CSSの場合:app/assets/stylesheets/application.css
code:app/javascript/packs/application.js
// This file is automatically compiled by Webpack, along with any other files
// present in this directory. You're encouraged to place your actual application logic in
// a relevant structure within app/javascript and only use these pack files to reference
// that code so it'll be compiled.
import Rails from "@rails/ujs"
import Turbolinks from "turbolinks"
import * as ActiveStorage from "@rails/activestorage"
import "channels"
Rails.start()
Turbolinks.start()
ActiveStorage.start()
CSSの場合、デフォルトだとSprocketsが管理するようになっている(Webpackerに任せることもできる)
その場合、マニフェストファイルはapp/assets/stylesheets/application.cssになる。
rails newしたばかりのapp/assets/stylesheets/application.cssには「これはマニフェストファイルです」と書いている。
code:app/assets/stylesheets/application.css
/*
* This is a manifest file that'll be compiled into application.css, which will include all the files
* listed below.
*
* Any CSS and SCSS file within this directory, lib/assets/stylesheets, or any plugin's
* vendor/assets/stylesheets directory can be referenced here using a relative path.
*
* You're free to add application-wide styles to this file and they'll appear at the bottom of the
* compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
* files in this directory. Styles in this file should be added after the last require_* statement.
* It is generally better to create a new file per style scope.
*
*= require_tree .
*= require_self
*/
= require_tree .や= require_selfはコメントアウトされているように見えるがこれはRails独自の設定記述方法。
code:zsh
❯ tree app/assets
app/assets
├── config
│ └── manifest.js
├── images
└── stylesheets
├── application.css
├── scaffolds.scss
└── users.scss
code:app/assets/config/manifest.js
//= link_tree ../images
//= link_directory ../stylesheets .css