Closed8
vite-plugin-imagemin-cache機能拡張
vite-plugin-imagemin-cacheについて
静的アセットおよびpublicディレクトリに含まれるPNG/JPEG/SVGを imagemin に通しつつキャッシュを保持してビルドの高速化を図るViteプラグイン(V2,V3対応)
本件プラグイン作成の経緯については以下を参照のこと。
実装済の機能
- 静的アセットに含まれる画像のキャッシュ機能
- ファイル名に含まれるハッシュを利用して判定
- publicディレクトリに含まれる画像のキャッシュ機能
- LokiJSによる永続化データストアを用意しCRCを保持して判定
- キャッシュの期限切れ処理
- 直近のn回以内のビルドないし直近のm秒以内のビルドのいずれでも使用されなかった場合に削除する
ToDo
- 上書きビルドにおける差分処理
- 静的アセットの画像でもCRCによる判定を使用できるようにする
- CRCを利用したキャッシュバスティング
キャッシュバスティング検討
- どのタイミングで何を使うか
- ビルド用
transformIndexHtml
フック(Vite)、または全て終わった後のcloseBundle
フック(Rollup) - 静的アセットは中間フォーマットの
__VITE_ASSET__hash__
をtransformIndexHtmlで加工する手がある(この時点でCSS/JSはバンドル済)-
/__VITE_ASSET__(.+?)__/g
→__VITE_ASSET__$1__?hash=$1
-
- publicディレクトリの画像はtransformIndexHtmlの時点でHTMLをパースして処理するのが手っ取り早いが、imageminの処理より前なのでキャッシュDBのCRCを使い回すことはできない
- publicディレクトリの内容と照合してリンク切れチェックができそう
- 分離してプラグインプリセットでまとめるか、またはプラグインを分けることも検討する
中間フォーマットはsearchとhashの有無で異なる。assetプラグイン参照。
__VITE_ASSET__<hash>__
__VITE_ASSET__<hash>__$_<url.search><url.hash>__
pnpm link
- リンクするパッケージで
pnpm link --global
- リンクされるのはビルドしたもの
- リンクしたパッケージを使用するプロジェクトで
pnpm link --global <package_name>
- 依存関係に同名のパッケージが存在する場合は削除する
- 解除は
pnpm unlink --global <package_name>
publicディレクトリのVite側の処理
-
copyDir(config.publicDir, outDir)
(build.ts line595)で丸ごとコピーしている - 現状プラグインによる「publicディレクトリに含まれる画像の処理」はVite本体が一度原本をコピーした後に圧縮したものを上書きしている → 常に上書きしないと原本が使用されてしまう
- 上書きを抑制するにはViteによるpublicディレクトリの処理をスキップしてプラグイン側で処理する必要がある
- 実装自体は容易だがVite本体のロジックをねじ曲げるのはあまり気が進まない……
- publicのコピーはユーザー設定でpublicDirが「空文字列」または
false
の時に無効になる -
configResolved
フックまで進むとViteが内部的に抱えているpublicDirは書き換えられない- 恐らく
config
フックの時点で判定を終えておく必要がある
- 恐らく
- 他方、上書き抑制の判定に使用予定だった
emptyOutDir
フラグは設定ファイル以外にCLIオプションでも変更される- CLIオプションが反映された状態で確認できるのは
configResolved
フックになってから
- CLIオプションが反映された状態で確認できるのは
- これらを勘案すると
emptyOutDir
の状態によってpublicDir
の内容を分岐させるのはViteの処理をプラグイン側で再実装する必要がありスマートでない
追加機能の整理
静的アセット/ファイル名ハッシュあり
-
上書きスキップ(キャッシュ判定流用方式)
- 同名のファイルが出力ディレクトリに存在していたらスキップする(
delete bundle[fileName]
)
- 同名のファイルが出力ディレクトリに存在していたらスキップする(
-
上書きスキップ(出力ファイル判定)- これいる?
-
キャッシュバスター
- transformIndexHtmlフックでハッシュをクエリとして付与する(prefix指定可)
静的アセット/ファイル名ハッシュなし
-
CRCで同一性チェックを行う
- publicディレクトリのファイルと同じ処理
-
またはViteが付与するSHAで同一性チェックを行う- generateBundleフックで取得する方法が存在するかどうか不明
-
上書きスキップ(出力ファイル判定)- これいる?
- ディレクトリ構造・ファイル名の再現
- 処理を分けるのは「同名ファイルの差し替えがあった場合に機能しない」ため
- キャッシュバスターはハッシュありと同一処理で問題ない
publicディレクトリ
-
二重コピー抑制
- Vite標準のコピー処理をキャンセルし、画像以外はそのままコピー、画像は圧縮してコピーする
-
上書きスキップ- 二重コピー抑制機能の使用を前提として、前回処理時とCRCが同じかつ同名のファイルが出力ディレクトリに存在していたらスキップする
- 一旦スキップ
-
キャッシュバスターHTMLをパースしクエリを付与する- 静的アセットで「ディレクトリ構造・ファイル名の再現」が実装できたため一旦スキップ
- キャッシュバスターはいつ処理するか、transformIndexHtmlフックかcloseBundleフックかそれ以外か
- CRCが再利用できるかどうか
以下の内容を盛り込んでマイナーバージョンを上げてリリースした。
- 静的アセット/ディレクトリ構造・ファイル名再現
- 静的アセット/CRCによる同一性検証(自動判定・手動判定)
- 静的アセット/キャッシュバスティング
- 静的アセット/上書き抑止(上書きビルド用)
- publicディレクトリ/二重コピー抑制
このスクラップは2022/07/21にクローズされました