propshaft README(翻訳)
Propshaftは、Railsのアセットパイプライン用ライブラリです。Propshaftは、以下のような時代に合わせて構築されました。
- HTTPコネクションを節約するためのアセットバンドルがもはや切実ではなくなった
- JavaScriptやCSSを専用のNode.jsバンドルでコンパイルするかブラウザに直接提供するようになった
- 帯域幅が増えたことでアセットの最小化(minify)の必要性が低くなった
これらの要因によって、Sprocketsのような従来のオプションと比べて劇的にシンプルかつ高速なアセットパイプラインを実現できるようになりました。
すなわち、Propshaftでは上記のような処理は行いません。Propshaftが提供するのは以下の機能です。
- コンフィグ可能な読み込みパス: アプリやgem内のさまざまな場所にあるディレクトリを登録して、それらがあたかも1つのパス上に置かれているかのように、すべてのパスのアセットを参照できるようになります。
- ダイジェストの付与: production環境では読み込みパスにあるすべてのアセットがコピー(またはコンパイル)され、そのすべてのファイル名にダイジェストハッシュが付与されます。すなわち、有効期限の長いキャッシュヘッダーを用いてパフォーマンスを向上させることが可能です。この処理中に変換方法を提供するマニフェストファイルが生成されるので、ダイジェストを付与されたアセットを論理パス経由で参照できるようになります。
- 開発用サーバー: developmentモードではアセットのプリコンパイルは不要です。同じ
asset_path
ヘルパーでこれらを参照すれば、developmentモードのサーバーでアセットを表示できます。 - 基本的なコンパイラ: 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_path
やimage_tag
やjavascript_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
というパターンかどうかを探します(このパターンはファイルがダイジェスト済みであることを示します)。
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-railsやcssbundling-railsなどのNodeベースのトランスパイラを利用する必要があります。
一方、JavaScriptやCSSを既にNodeベースのセットアップでバンドルしていれば、Propshaftを手軽に導入できます。この場合、バンドルやトランスパイルに別のツールを使う必要はなく、単にダイジェスト化して提供するだけで完了します。
しかしPropshaftは、新規アプリケーションでデフォルトのimport-mapアプローチを用いる場合にもうまく機能します(vanilla CSSを扱う用意ができていれば)。
ライセンス
Propshaft is released under the MIT License.
概要
MITライセンスに基づいて翻訳・公開いたします。