10中9つのWebプロジェクトで発生しているアイコンのパフォーマンス問題

10中9つのWebプロジェクトで発生しているアイコンのパフォーマンス問題

ダッシュボードやSaaSサイトがアイコンを誤った方法で配信している可能性が高い理由と、監査で判明したこと

10中9つのWebプロジェクトで発生しているアイコンのパフォーマンス問題

数週間前、ある人物がランダムに選んだ12のオープンソース・フロントエンドリポジトリを監査し、それぞれがどのようにアイコンを配信しているかを調査しました。ビジュアルデザインではなく、実際の配信メカニズムについてです。調査結果は驚くほど一貫しており、パフォーマンス予算が厳しくなり、ユーザーがあらゆる場所で軽快なインターフェースを期待する今日(2026年6月30日)、この問題はかつてないほど重要になっています。

なぜ今、この問題に注目すべきなのでしょうか?それは、アイコンの配信が人々が無視しがちな「目に見えない」最適化の1つだからです。ほとんどのパフォーマンスチェックリストはJavaScriptのバンドルサイズや画像の最適化に重点を置いていますが、アイコンは精査されることなく見過ごされがちです。そして、12のプロジェクト中9つが同じ問題を抱えていたということは、注目に値するシグナルです。

誰もが知っているおなじみの原因

まずは、ほとんどの開発者が回避することをすでに学んでいるものから始めましょう。

アイコンフォント (Font Awesomeなど)は、多くの場合20KB以上、時にはそれ以上の大容量ファイルを読み込みます。ほんの一握りのアイコンを使うためだけに、フォント全体を配信することになります。確かにブラウザはこれらをキャッシュしますが、使用するものと配信するもののトレードオフとしては好ましくありません。現在では、ほとんどのチームがこのことを理解しています。

インラインSVG はモダンな解決策のように見えました。SVGコードをHTMLに直接埋め込みます。追加のHTTPリクエストが発生せず、スタイリングを完全制御できます。しかし、インラインSVGにはあまり語られない欠点があります。すべてのページで同じであっても、ページを読み込むたびにそのコードが再パースおよび再描画されます。また、HTMLが肥大化し、パースやDOM構築が遅くなります。

スプライトシート (複数のアイコンを含む1つの大きなSVGまたはPNG)はHTTPリクエストを削減しますが、画像から適切な部分を抽出することで複雑さが増します。また、動作させるにはビルドステップまたはランタイムライブラリが必要です。

Base64エンコーディング SVGやPNGをCSSやdata属性に直接変換しますか?キャッシュを破綻させることに気付くまでは便利に思えます。スタイルシートを変更するたびに、すべてのアイコンが再送信されます。

実際に問題を発生させ続けているパターン

監査で判明したのは次のことです。ほとんどのプロジェクトは、アプリケーションコードと一緒にアイコンをバンドルする形でアイコンシステムを配信しています。

ダッシュボードを構築しているとします。以下のような Icon コンポーネントを含むコンポーネントライブラリがあるとします。そのコンポーネントはすべてのSVGアイコンをインポートするか、巨大なオブジェクトから参照します。本番用にビルドするたびに、バンドラーはすべてのアイコンファイルを処理、最適化し、メインのJavaScriptにバンドルします。アイコンがクリティカルパスの一部になってしまうのです。

これは実践において何を意味するのでしょうか?

1つ目: JavaScriptが読み込まれ実行されるまで、ブラウザはアイコンを使用できません。500KBのバンドルに200KBのアイコンが埋め込まれて配信されると、ユーザーが空白のページを見る時間が長くなります。アイコンの描画がスクリプトのパースによってブロックされるためです。

2つ目: アイコンの変更とコードの変更の間で、キャッシュ無効化の区別がありません。アイコンの色を1つ変更しただけで、バンドル全体のハッシュが変更されます。ユーザーはすべてを再ダウンロードすることになります。

3つ目: 使用されていないアイコンも配信されます。バンドラーは未使用のJavaScript関数のツリーシェイキングには優れていますが、大きなマニフェストで参照されている未使用のSVGファイルには対応できません。その無駄な容量を抱え込むことになります。

4つ目: アイコンがレンダリングをブロックするようになります。低速なネットワークでは、バンドル全体の到着を待つことが、アイコンを待つことにもなります。個別のリソースとして並行して読み込まれるのではなく、スクリプトの後ろに直列化されます。

より良いパターン:アイコンをコードから切り離す

パフォーマンスが良好だったプロジェクトは、ある1つのことを異なって行っていました。それは、アプリケーションのJavaScriptとは別にアイコンを配信していたことです。

外部SVGファイルとして。 アイコンは以下のようなURLに配置されます /assets/icons/check.svg。ブラウザは必要なときにそれをリクエストし、独立してキャッシュし、他の静的アセットと同様に扱います。ビルド時にHTML内でアイコンをインライン化することも、ランタイム時に遅延読み込みすることもできます。いずれにせよ、アプリケーションコードと一緒にバンドルされることはありません。

なぜこれでうまくいき、効果的なのでしょうか?

  • 並行読み込み。 アイコンはJavaScriptにブロックされることなく、独自のタイミングで取得されます。
  • キャッシュの分離。 アイコンを変更した場合、そのアイコンのみが再ダウンロードされます。アプリのバンドルには影響しません。
  • ビルドの効率化。 バンドラーがアイコンを処理しなくなります。コードに集中できるため、ビルドが高速化します。
  • オプションの遅延読み込み。 特定のフローにのみ表示されるアイコンもあります。事前ではなく、オンデマンドで読み込むことができます。

自身のプロジェクトを監査する方法

自身のセットアップにこの問題があるかどうかを確認したい場合、以下のアプローチが簡単です。

ステップ1:アイコンが定義されている場所を特定する

コードベース内で、以下のような Icon コンポーネントや中心となるアイコンファイルを探します。これは src/components/Icon.tsx, src/icons/index.tsや、類似の場所に存在する可能性があります。すべてのSVGアイコンをインポートまたは参照しているファイルを検索します。

ステップ2:何がバンドルされているかを確認する

本番用にプロジェクトをビルドし、出力されたバンドルを検査します。以下のようなツールを使用するか、 webpack-bundle-analyzer またはソースマップを確認します。アイコンはJavaScriptバンドル内に表示されますか、それとも外部ファイルとして存在しますか?

バンドル内にエンコードされたSVGコンテンツが含まれている場合、問題のパターンに該当しています。

ステップ3:読み込み時間への影響を測定する

低速な3G接続でアプリを読み込みます(ブラウザのDevToolsでスロットリングを設定)。Networkタブを観察します。アイコンが表示される前にメインのJavaScriptバンドルの読み込みが完了しますか?もしそうなら、アイコンはバンドルされており、描画をブロックしています。

ステップ4:キャッシュの挙動を確認する

1つのアイコンにわずかな変更を加えます(色を変更するだけでも構いません)。再ビルドしてデプロイします。変更前後のバンドルハッシュを比較します。アプリのバンドルハッシュ全体が変更されている場合、アイコンがコードと絡み合っています。

修正方法

ステップ1:アイコンを別のディレクトリに移動する

以下のようなフォルダを作成します: public/icons/ (静的アセットディレクトリを使用する場合)または src/assets/icons/。各アイコンを個別のSVGファイルとして保存します: check.svg, close.svg, arrow.svgなど。コンポーネントコードとは分けて管理してください。

ステップ2:Iconコンポーネントを更新する

SVGコンテンツをインポートする代わりに、ファイル名でアイコンを参照します:

function Icon({ name, size = 24 }) {
  return <img src={`/icons/${name}.svg`} alt={name} width={size} height={size} />;
}

または、SVGスタイリング(色やストロークの変更など)が必要な場合:

function Icon({ name, size = 24, color = 'currentColor' }) {
  return <svg width={size} height={size} className="icon"><use href={`/icons/${name}.svg#${name}`} /></svg>;
}

ステップ3:本番用にSVGを最適化する

以下のようなツールでアイコンを処理します: svgo (コマンドライン最適化ツール)。見た目を変更することなく、未使用のメタデータを削除し、パスを単純化し、ファイルサイズを削減します。

npx svgo public/icons/*.svg

ステップ4:テストと測定

本番用にビルドします。バンドルサイズを確認します。縮小されているはずです。低速な接続でアプリを読み込みます。JavaScript全体が読み込まれた後ではなく、HTTPリクエストが完了するとすぐにアイコンが表示されるはずです。

結論

アイコンの配信は、問題が表面化するまでは目立たないことがよくあります。アイコンをアプリケーションコードと一緒にバンドルすると、本来独立しているべき2つのもの、すなわちコードの変更とビジュアルアセットが結合されてしまいます。アイコンを個別の静的ファイルとして配信してこれらを切り離すことで、最小限の手間でパフォーマンス、キャッシュ、ビルド時間が向上します。ハイパフォーマンスなプロジェクトの多くはこれを自然に行っています。これでその理由が分かったはずです。

メリット

  • アイコンはアプリケーションコードの後に順次読み込まれるのではなく、コードと並行して読み込まれます。
  • アイコンを変更しても、アプリケーションのバンドルキャッシュ全体が無効化されることはありません。
  • アプリケーションのJavaScriptバンドルが小さくなるため、パースと実行が高速化します。
  • バンドラーでアイコンが処理されないため、ビルド時間が向上します。
  • 新しいアイコンの追加が簡単です。ディレクトリにSVGファイルを配置するだけです。
  • オプショナルなUIフローのためにアイコンを遅延読み込みすることが簡単になります。

デメリット

  • ユニークなアイコンごとに1つの追加HTTPリクエストが必要になります(ただし、ブラウザは並行処理とキャッシュを強力に行います)。
  • コードベース全体でファイルパスと命名規則を管理する必要があります。
  • ビルドステップやランタイムでのフェッチなしに、コンポーネントのpropsに依存するSVGスタイルを簡単にインライン化できません。
  • 静的アセットの配信に慣れていないチームにとっては、コンポーネントのインポートよりも少し不便に感じるかもしれません。
  • 適切なキャッシュヘッダーがない古いデプロイ環境では、古いアイコンファイルが配信されるリスクがあります。

注意点

上記の例およびファイルパス(/icons/, check.svg, Icon コンポーネント名)は例示的なプレースホルダーです。プロジェクトの構造に合わせて調整してください。本番環境に配信する前に、デスクトップとモバイルの両方のブラウザでアイコンの描画を徹底的にテストしてください。パフォーマンス上のメリットが実際に得られるよう、WebサーバーまたはCDNがアイコンファイルに適切なキャッシュヘッダー(Cache-Control: public, max-age=31536000)を送信していることを確認してください。自己責任で進行し、特定のネットワークおよびデバイス環境でパフォーマンスの向上を検証してください。

よくある質問

  • WebパフォーマンスにおけるSVGアイコンとPNGアイコンの違いは何ですか?
  • Font Awesomeのようなアイコンライブラリを使用すべきですか、それとも独自のアイコンシステムを構築すべきですか?
  • SVGファイルを最適化して、可能な限り高速な読み込み時間を実現するにはどうすればよいですか?
  • 外部ファイルとして配信されている場合でも、CSSで個々のアイコンをスタイリングできますか?
  • ユーザーの操作に基づいて色を変更する必要があるアイコンを扱う最善の方法は何ですか?
  • パフォーマンスが低下する前に、アイコンに対して行っても問題ないHTTPリクエスト数はどのくらいですか?
  • 初回訪問時にサービスワーカーを使用してアイコンをローカルにキャッシュすべきですか?
  • 現在のアイコン配信方法を分析し、パフォーマンス上の問題を特定するにはどのツールを使用できますか?

タグ

#svg #web-performance #frontend-optimization #icon-systems #asset-management #caching-strategy #web-development #performance-audit

Free field guide

Linux Server Hardening Checklist

30 practical steps to take a fresh Linux box from default to defensible. Enter your email — you'll get the PDF instantly, plus new posts on Linux, security & AI.