LoginSignup
3
1

More than 1 year has passed since last update.

Railsで画像をpublic配下ではなくアセットパイプラインを通して配置する

Posted at

指摘されたこと

RailsとReactで動く画像を表示したかったので、画像をpublic/img/フォルダに置いてこのように書きました。

Hoge.tsx
return (
  <>
    <img src="/img/hoge.jpg" alt="hoge" />
  </>
)

すると先輩から下記のように指摘を受けました。無断で転載します。

画像のパスはRailsから渡したほうがいいと思います。
public配下ではなく、アセットパイプラインを通したやつを渡してください。
動きはするんだけど、もし画像を差し替えるとなったときに、パスが固定だとしばらくブラウザのキャッシュが働いてすぐに切り替わらないので。アセットパイプラインを通すと、ファイル名にランダムな文字列が付いて、画像が変わるたびに別のパスになります。

なんとなく言いたいことはわかるんだけど、「なんとなく」を潰したいので、きちんと咀嚼しながら修正します。

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

JS,CSS,画像などのファイルを最小化して連結するためのフレームワーク。

Railsガイドでも、アセットパイプラインが推奨されているとのこと。

以前のRailsでは、すべてのアセットはpublicディレクトリの下のimages、javascripts、stylesheetsなどのサブフォルダに置かれました。アセットパイプライン導入後は、app/assetsディレクトリがアセットの置き場所として推奨されています。
Railsガイドv7.0 - アセットパイプライン「2 アセットパイプラインの利用方法」

なぜアセットパイプラインを通すのか

先輩のコメントそのまんまなんですが、パイプラインを通すとアセットにランダムな文字列を生成して割り当てるみたい。
将来、「画像を置き換えたい、だけど同じファイル名で」となった時に、public配下だと、ファイル名が一緒なので、ブラウザがキャッシュに「あ、そのファイルの画像名なら取りに行かなくてもキャッシュで持ってるぜ」となってサーバーに新しい画像を取りに行ってくれない。アセットパイプラインを通すと、名前が同じであっても違うアセットとみなされてファイル名が別になる。それで置き換えたら即時にその変更が反映されるようになるということですね。これ本記事の最後で検証します。百聞は一見に如かず。

どうやってアセットパイプラインを通したやつを渡すか

画像をapp/assets/images配下に置きます。
画像のパスを取得するには、Railsのメソッドimage_pathが使えそうでした。

ビューで下記のように書きます。

erb
<%= react_component(
  "App",
  props: {
    hogeImage: image_path("hoge.jpg"),
  },
  prerender: false
) %>

本課題とは関係ないですが、コントローラなどで画像のパスを取得したい場合は、view_context.image_pathとすると取得できそうです。これでReactの画面で画像を表示できました。

画像のパスはどうなったのか

先輩の指摘「アセットパイプラインを通すと、ファイル名にランダムな文字列が付いて、画像が変わるたびに別のパスになります。」を検証するために、パスがどうなるのか見てみます。HTMLのimgタグのsrcに何が入るのか。

public配下に置いた場合。

public配下
/img/hoge.jpg

アセットパイプラインを通した場合。ほほう。画像ファイル名の後にランダムな文字列が入っている!

アセットパイプライン
/assets/hoge-c0d7ed0a339ac8017a3cc703c3bc1353574cc4d5aad524b43046ff35a9cf495c.jpg

ブラウザをリロードしてもう一度表示してみる。当然ながらランダムな文字列は変わっていない。

アセットパイプラインでリロード
/assets/hoge-c0d7ed0a339ac8017a3cc703c3bc1353574cc4d5aad524b43046ff35a9cf495c.jpg

同じ名前だが中身は違うファイル名で置き替えてみる。文字列が変わった!

アセットパイプライン(画像を置き換える)
/assets/hoge-2e64510ea882790984b0353c7c7b0ca5c31c78af933d5c09070c7d79aad5204c.jpg

試しに同じファイル名で中身はさっきのファイルに戻してみる。文字列はさっきのに戻るのか、新しいのが生成されるのか。。。さっきのに戻った!ほほう。

アセットパイプライン(同じファイル名で前の画像に戻す)
/assets/hoge-c0d7ed0a339ac8017a3cc703c3bc1353574cc4d5aad524b43046ff35a9cf495c.jpg
3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1