/var/log/jsoizo

メモ帳 技術とか趣味とか

Viteはライブラリモードの時にアセットを自動的にbase64エンコードしてくれる

たとえばコンポーネントライブラリを作ろうとしていて、そのコンポーネント内で特定の画像ファイルをbackground-imageで埋め込みたいというケースを考える。
このとき、画像をどうやってパッケージに含めるか、とか、ライブラリ利用側でのパス解決がうまいこといくように工夫しなきゃいけない、とかが悩みだったりする。

以下のようなsassファイルに背景画像を設定する記述があったとする

.logo {
    background-image: url("relative/path/to/image.png");
}

この記述のままビルドされた時にurlの中身がそのままだと、利用側プロジェクトにおいてはプロジェクトルートにおける relative/path/to/image.png を参照しようとしてファイルが見つからずレンダリングにコケるだろう。

viteではその辺の問題を回避するために、 ライブラリモード時はすべてのアセットをインライン化しbase64エンコードしてくれる (してしまう)。

.logo {
    background-image: url(data:image/png;base64,iVBORw0KGgo...);
}

特に気にしなくてもライブラリの利用先で画像が確実に読み込まれるメリットが有る一方で、base64エンコードされるということは配布ファイル単体のサイズはでっかくなるので、たとえばsassファイルとかだと最終的に出力されるスタイルシートのファイルがbase64エンコードされた画像のせいでバカでかくなってしまう。ファイルが大きくなると当然ダウンロードにかかる時間が増えるのでフロントエンドのレイアウト確定やレンダリングの速度に影響が出てしまう。。。

ゆえに、むしろ ライブラリモードで作るときはアセットが自動的にbase64エンコードされるので予め表現ごとにリサイズした画像をちゃんと用意しておかないと生成物が肥大化しがちである ということを認識する必要がある。minify等での最適化しようがないので気をつけたほうが良い。

この振る舞いはドキュメント的には build.assetsInlineLimit の注意事項として書かれているだけなので見落としがちである。

vitejs.dev

これを拒否できるオプションを用意してくれ的なissueを切っている人もいる。気持ちはわかる。

github.com

冒頭に書いたような悩みを持っていたところにChatGPT大先生から"画像base64しとけ"的なお告げを受けまして。でこの仕様を知ったときvite最高だなって思ったんだけど、生成されるcssファイルのサイズのことを冷静に考えたら画像を現実的なサイズにリサイズしなきゃとか色々考えることになって(´;ω;`)ウッ…ってなっている。