Tech Racho エンジニアの「?」を「!」に。
  • Ruby / Rails関連

Propshaft gem README(翻訳)

概要

MITライセンスに基づいて翻訳・公開いたします。


rails/propshaft - GitHub

propshaft README(翻訳)

Propshaftは、Railsのアセットパイプライン用ライブラリです。Propshaftは、以下のような時代に合わせて構築されました。

  • HTTPコネクションを節約するためのアセットバンドルがもはや切実ではなくなった
  • JavaScriptやCSSを専用のNode.jsバンドルでコンパイルするかブラウザに直接提供するようになった
  • 帯域幅が増えたことでアセットの最小化(minify)の必要性が低くなった

これらの要因によって、Sprocketsのような従来のオプションと比べて劇的にシンプルかつ高速なアセットパイプラインを実現できるようになりました。

すなわち、Propshaftでは上記のような処理は行いません。Propshaftが提供するのは以下の機能です。

  1. コンフィグ可能な読み込みパス: アプリやgem内のさまざまな場所にあるディレクトリを登録して、それらがあたかも1つのパス上に置かれているかのように、すべてのパスのアセットを参照できるようになります。
  2. ダイジェストの付与: production環境では読み込みパスにあるすべてのアセットがコピー(またはコンパイル)され、そのすべてのファイル名にダイジェストハッシュが付与されます。すなわち、有効期限の長いキャッシュヘッダーを用いてパフォーマンスを向上させることが可能です。この処理中に変換方法を提供するマニフェストファイルが生成されるので、ダイジェストを付与されたアセットを論理パス経由で参照できるようになります。
  3. 開発用サーバー: developmentモードではアセットのプリコンパイルは不要です。同じasset_pathヘルパーでこれらを参照すれば、developmentモードのサーバーでアセットを表示できます。
  4. 基本的なコンパイラ: Propshaftの設計では、すべてのトランスパイラ機能を提供するわけではないことが明示されています。よりよいトランスパイラは他にもあります。しかし、Propshaftはシンプルな入力->出力コンパイラセットアップを提供し、デフォルトではCSSでのurl(asset)関数呼び出しをurl(digested-asset)に変換し、ソースマッピングも同様に変換するために使われます。

🔗 インストール

Rails 8以降の新規アプリケーションでは、Propshaftがデフォルトのアセットパイプラインになります。rails new myapp -a propshaftでPropshaftを有効にした新しいアプリケーションの開発を始められます。既存のアプリケーションについては、アップグレードガイドに記載されている手順を参照してください。

🔗 利用法

Propshaftは、config.assets.pathsで設定されたすべてのパスにあるアセットを提供可能にし、プリコンパイル時にはすべてのアセットをpublic/assetsにコピーします。この振る舞いは、バンドル済みアセットに明示的に含まれていないアセットを明示的にコピーしないSprocketの振る舞いとは異なります。

ただし、config.assets.excluded_pathsで追加したパスは除外できます。これは、たとえばDart Sass for Railsなどのコンパイラの入力としてapp/assets/stylesheetsだけを使い、これらの入力ファイルを読み込みパスの一部に含めたくない場合に便利です( Rails.root.join("app/assets/stylesheets")のように完全パスを追加するのをお忘れなく)。

これらのアセットは、asset_pathimage_tagjavascript_include_tagといった通常のヘルパータグで論理パスから参照可能です。これらの論理参照は、rails assets:precompileが実行されると自動的にダイジェストを考慮したパスに変換されます(public/assets/.manifest.jsonにあるJSONマッピングファイルを経由)。

追記(2022/07/05)

以下の記述は削除されました。

また、Propshaftにはasset-path("image.svg")というCSS関数が同梱され、コンパイル時にはurl("/assets/image-f2e1ec14d6856e1958083094170ca6119c529a73.svg")に変換されます。この関数は、あらゆる.cssファイルに適用されます。

🔗 ダイジェスト済みアセットをCSSやJavaScriptから参照する

Propshaftは、CSS内のアセット参照を自動的にダイジェスト付きのファイル名に変換することで利用可能にします。たとえば、background: url("/bg/pattern.svg")というアセット参照は、background: url("/assets/bg/pattern-2169cbef.svg")のように変換してからスタイルシートを配信します。

JavaScript内のアセット参照については、RAILS_ASSET_URLという疑似メソッドを用いて手動で変換をトリガーする必要があります。このメソッドは、以下のように利用できます。

export default class extends Controller {
  init() {
    this.img = RAILS_ASSET_URL("/icons/trash.svg")
  }
}

これにより、上の参照は以下のように変換されます。

export default class extends Controller {
  init() {
    this.img = "/assets/icons/trash-54g9cbef.svg"
  }
}

ダイジェスト追加をスキップするには

JavaScriptファイルとそのsource mapで行っているように、複数のファイルをPropshaft経由で相互参照する必要がある場合は、ファイル名を安定させるために、それらのファイルを事前にダイジェスト化しておかなければなりません。Propshaftは、アセットファイル名の末尾が-[ダイジェスト].digested.jsというパターンかどうかを探します(このパターンはファイルがダイジェスト済みであることを示します)。

🔗 サブリソース完全性(SRI)(2025/07追加)

Propshaftは、アセットを悪意のある改変から保護するためにサブリソース完全性(SRI: Subresource Integrity)をサポートしています。サブリソース完全性によってブラウザ側で暗号ハッシュをチェックすることで、CDNなどから取得したリソースが不正に改ざんされていないことが保証されます。

🔗 サブリソース完全性を有効にする

サブリソース完全性のサポートを有効にするには、Railsアプリケーションの設定でそのためのハッシュアルゴリズムを指定する必要があります。

config.assets.integrity_hash_algorithm = "sha384"

以下のハッシュアルゴリズムを指定可能です。

  • "sha256" - SHA-256(最も一般的)
  • "sha384" - SHA-384(高度なセキュリティ向けに推奨)
  • "sha512" - SHA-512(最強)

🔗 SRIをビューで有効にする

サブリソース完全性が有効になれば、アセットヘルパーにintegrity: trueオプションを渡すことで有効にできます。

<%= stylesheet_link_tag "application", integrity: true %>
<%= javascript_include_tag "application", integrity: true %>

これにより、以下のように完全性ハッシュが生成されます。

<link rel="stylesheet" href="/assets/application-abc123.css"
      integrity="sha384-xyz789...">
<script src="/assets/application-def456.js"
        integrity="sha384-uvw012..."></script>

重要: サブリソース完全性は、セキュアなコンテキスト(HTTPS)やローカルのdevelopment環境でのみ機能します。セキュリティ上の理由で、production環境でHTTP配信を行う場合は完全性ハッシュが自動的に省略されます。

🔗 スタイルシートに完全性チェックを一括で含める

Propshaftでは、stylesheet_link_tagで以下のように完全性チェックを一括で含められます。

<%= stylesheet_link_tag :all, integrity: true %>  <!-- 全スタイルシートが対象 -->
<%= stylesheet_link_tag :app, integrity: true %>  <!-- app/assetsのスタイルシートのみが対象 -->

developmentモードでのパフォーマンスを改善する(2023/01/10追加)

Propshaftは、キャッシュのクリアが必要かどうかを判断するために、アセットが更新されているかどうかをすべてのリクエストの直前にチェックします。この確認には、アプリケーションで設定されているファイルウォッチャー(デフォルトではActiveSupport::FileUpdateChecker)が使われます。

プロジェクトで使われているアセットが非常に多い場合は、Gemfileのdevelopmentグループにlisten gemを追加し、development.rb環境ファイルに以下の行を追加してください。

config.file_watcher = ActiveSupport::EventedFileUpdateChecker

SprocketsからPropshaftへの移行

PropshaftはSprocketsよりも機能がかなり少ないので、移行が望ましい場合でもそれなりの作業量が必要になるかもしれません。特に、アプリケーションがCoffeeScriptやSassなどのトランスパイラ機能を提供するためにSprocketsに依存している場合や、トランスパイラを提供するgemに依存している場合は、作業量が増える傾向にあります。トランスパイルをやめるか、jsbundling-railscssbundling-railsなどのNodeベースのトランスパイラを利用する必要があります。

一方、JavaScriptやCSSを既にNodeベースのセットアップでバンドルしていれば、Propshaftを手軽に導入できます。この場合、バンドルやトランスパイルに別のツールを使う必要はなく、単にダイジェスト化して提供するだけで完了します。

しかしPropshaftは、新規アプリケーションでデフォルトのimport-mapアプローチを用いる場合にもうまく機能します(vanilla CSSを扱う用意ができていれば)。

ライセンス

Propshaft is released under the MIT License.

関連記事

Rails: Sprockets->Propshaftアップグレードガイド(翻訳)

Rails: importmap-rails gem README(翻訳)


CONTACT

TechRachoでは、パートナーシップをご検討いただける方からの
ご連絡をお待ちしております。ぜひお気軽にご意見・ご相談ください。