Closed8

vite-plugin-imagemin-cache機能拡張

macropygiamacropygia

vite-plugin-imagemin-cacheについて

https://www.npmjs.com/package/@macropygia/vite-plugin-imagemin-cache

静的アセットおよびpublicディレクトリに含まれるPNG/JPEG/SVGを imagemin に通しつつキャッシュを保持してビルドの高速化を図るViteプラグイン(V2,V3対応)

本件プラグイン作成の経緯については以下を参照のこと。

https://qiita.com/macropygia/items/d37fd20a16fcef26914b

実装済の機能

  • 静的アセットに含まれる画像のキャッシュ機能
    • ファイル名に含まれるハッシュを利用して判定
  • publicディレクトリに含まれる画像のキャッシュ機能
    • LokiJSによる永続化データストアを用意しCRCを保持して判定
  • キャッシュの期限切れ処理
    • 直近のn回以内のビルドないし直近のm秒以内のビルドのいずれでも使用されなかった場合に削除する

ToDo

  • 上書きビルドにおける差分処理
  • 静的アセットの画像でもCRCによる判定を使用できるようにする
  • CRCを利用したキャッシュバスティング
macropygiamacropygia

キャッシュバスティング検討

  • どのタイミングで何を使うか
  • ビルド用 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ディレクトリの内容と照合してリンク切れチェックができそう
  • 分離してプラグインプリセットでまとめるか、またはプラグインを分けることも検討する
macropygiamacropygia

中間フォーマットはsearchとhashの有無で異なる。assetプラグイン参照。

  • __VITE_ASSET__<hash>__
  • __VITE_ASSET__<hash>__$_<url.search><url.hash>__
macropygiamacropygia

pnpm link

  • リンクするパッケージで pnpm link --global
    • リンクされるのはビルドしたもの
  • リンクしたパッケージを使用するプロジェクトで pnpm link --global <package_name>
    • 依存関係に同名のパッケージが存在する場合は削除する
    • 解除は pnpm unlink --global <package_name>
macropygiamacropygia

publicディレクトリのVite側の処理

  • copyDir(config.publicDir, outDir) (build.ts line595)で丸ごとコピーしている
  • 現状プラグインによる「publicディレクトリに含まれる画像の処理」はVite本体が一度原本をコピーした後に圧縮したものを上書きしている → 常に上書きしないと原本が使用されてしまう
  • 上書きを抑制するにはViteによるpublicディレクトリの処理をスキップしてプラグイン側で処理する必要がある
    • 実装自体は容易だがVite本体のロジックをねじ曲げるのはあまり気が進まない……
macropygiamacropygia
  • publicのコピーはユーザー設定でpublicDirが「空文字列」または false の時に無効になる
  • configResolved フックまで進むとViteが内部的に抱えているpublicDirは書き換えられない
    • 恐らく config フックの時点で判定を終えておく必要がある
  • 他方、上書き抑制の判定に使用予定だった emptyOutDir フラグは設定ファイル以外にCLIオプションでも変更される
    • CLIオプションが反映された状態で確認できるのは configResolved フックになってから
  • これらを勘案すると emptyOutDir の状態によって publicDir の内容を分岐させるのはViteの処理をプラグイン側で再実装する必要がありスマートでない
macropygiamacropygia

追加機能の整理

静的アセット/ファイル名ハッシュあり

  • 上書きスキップ(キャッシュ判定流用方式)
    • 同名のファイルが出力ディレクトリに存在していたらスキップする( delete bundle[fileName]
  • 上書きスキップ(出力ファイル判定)
    • これいる?
  • キャッシュバスター
    • transformIndexHtmlフックでハッシュをクエリとして付与する(prefix指定可)

静的アセット/ファイル名ハッシュなし

  • CRCで同一性チェックを行う
    • publicディレクトリのファイルと同じ処理
  • またはViteが付与するSHAで同一性チェックを行う
    • generateBundleフックで取得する方法が存在するかどうか不明
  • 上書きスキップ(出力ファイル判定)
    • これいる?
  • ディレクトリ構造・ファイル名の再現

  • 処理を分けるのは「同名ファイルの差し替えがあった場合に機能しない」ため
  • キャッシュバスターはハッシュありと同一処理で問題ない

publicディレクトリ

  • 二重コピー抑制
    • Vite標準のコピー処理をキャンセルし、画像以外はそのままコピー、画像は圧縮してコピーする
  • 上書きスキップ
    • 二重コピー抑制機能の使用を前提として、前回処理時とCRCが同じかつ同名のファイルが出力ディレクトリに存在していたらスキップする
    • 一旦スキップ
  • キャッシュバスター
    • HTMLをパースしクエリを付与する
    • 静的アセットで「ディレクトリ構造・ファイル名の再現」が実装できたため一旦スキップ

  • キャッシュバスターはいつ処理するか、transformIndexHtmlフックかcloseBundleフックかそれ以外か
    • CRCが再利用できるかどうか
macropygiamacropygia

以下の内容を盛り込んでマイナーバージョンを上げてリリースした。

  • 静的アセット/ディレクトリ構造・ファイル名再現
  • 静的アセット/CRCによる同一性検証(自動判定・手動判定)
  • 静的アセット/キャッシュバスティング
  • 静的アセット/上書き抑止(上書きビルド用)
  • publicディレクトリ/二重コピー抑制
このスクラップは2022/07/21にクローズされました