Font Awesome アイコンのセルフホスティングを簡単にする新API

shoelace-style/webawesome

setIconPath() / getIconPath() の追加により、デフォルトアイコンライブラリをFont Awesome CDNからセルフホスト環境へ切り替える手段が公式に提供されました。上級者向けには getIconFolder() のエクスポートも追加され、カスタムリゾルバーの実装にも対応しています。

背景

Web Awesomeのデフォルトアイコンライブラリは、Font AwesomeのCDNからSVGを取得する設計になっていました。#1423 で報告されているように、Font Awesome Pro+ユーザーを含む多くのユーザーがアイコンをセルフホストしたいという要望を持っていましたが、公式なAPIが存在しなかったため、ユーザーは registerIconLibrary() を使って独自のリゾルバーをゼロから実装する必要がありました。

Font Awesomeのダウンロードアーカイブには、solid/regular/brands/ などのサブフォルダを持つ svgs ディレクトリが含まれています。しかし、このフォルダ構造を正しく解決するロジック(family/variantからフォルダ名へのマッピング)はライブラリ内部に閉じており、ユーザーが再利用できませんでした。このPRはその制約を取り除くものです。

技術的な変更

setIconPath() / getIconPath() の追加

base-path.tsiconPath というモジュールスコープの変数が追加され、アイコンの解決先パスを保持するようになりました。

変更後の packages/webawesome/src/utilities/base-path.ts(追加部分):

let iconPath = '';

export function setIconPath(path: string) {
  iconPath = path;
}

export function getIconPath() {
  return iconPath.replace(/\/$/, '');
}

getIconPath() は末尾のスラッシュを正規化して返します。これは既存の getBasePath() と同じパターンであり、設計の一貫性が保たれています。

デフォルトライブラリのURL解決ロジックの変更

library.default.tsgetIconUrl() 関数が変更され、iconPath が設定されている場合はCDNの代わりにそのパスを使用するようになりました。

変更前:

function getIconUrl(name: string, family: string, variant: string) {
  const kitCode = getKitCode();
  const isPro = kitCode.length > 0;
  let folder = 'solid';
  // ... folderの決定ロジック ...

  // Use the default CDN
  return isPro
    ? `https://ka-p.fontawesome.com/releases/v${FA_VERSION}/svgs/${folder}/${name}.svg?token=${encodeURIComponent(kitCode)}`
    : `https://ka-f.fontawesome.com/releases/v${FA_VERSION}/svgs/${folder}/${name}.svg`;
}

変更後:

export function getIconFolder(_name: string, family: string, variant: string) {
  let folder = 'solid';
  // ... folderの決定ロジック(同一) ...
  return folder;
}

function getIconUrl(name: string, family: string, variant: string) {
  const folder = getIconFolder(name, family, variant);
  const iconBase = getIconPath();

  if (iconBase) {
    return `${iconBase}/${folder}/${name}.svg`;
  }

  const kitCode = getKitCode();
  const isPro = kitCode.length > 0;

  return isPro
    ? `https://ka-p.fontawesome.com/releases/v${FA_VERSION}/svgs/${folder}/${name}.svg?token=${encodeURIComponent(kitCode)}`
    : `https://ka-f.fontawesome.com/releases/v${FA_VERSION}/svgs/${folder}/${name}.svg`;
}

family/variantからフォルダ名を決定していたロジックが getIconFolder() として切り出され、export されました。getIconUrl() はこれを呼び出す形にリファクタリングされています。

パブリックAPIへのエクスポート追加

webawesome.ts のエントリーポイントに3つのシンボルが追加されました。

export { getIconFolder } from './components/icon/library.default.js';
export { getBasePath, getIconPath, getKitCode, setBasePath, setIconPath, setKitCode } from './utilities/base-path.js';

これにより、setIconPathgetIconPathgetIconFolder の3関数が /dist/webawesome.js からインポート可能になります。

設計判断

iconPath が未設定の場合は従来のCDN動作にフォールバックする 設計が採用されました。getIconPath() が空文字列を返す場合(デフォルト状態)、getIconUrl() はkitCodeの有無に応じたCDN URLを引き続き構築します。これにより、setIconPath() を呼ばない既存ユーザーへの影響はゼロです。

getIconFolder()export する判断も注目に値します。フォルダ名の決定ロジックはFamily(classic/sharpなど)とVariant(solid/regularなど)の組み合わせによる複雑な条件分岐を含みます。このロジックを内部に閉じたままカスタムリゾルバーの例だけを提示する選択肢もありましたが、ヘルパー関数として公開することで、ユーザーが独自のリゾルバーを registerIconLibrary() と組み合わせて実装する際に、同じロジックを再実装しなくて済むようになっています。

setIconPath() はコンポーネントのロード前に呼ばれることを想定しており、その旨がJSDocコメントに明記されています。setBasePath() と同様の事前設定パターンに倣っており、ライブラリの設定APIとして一貫したインターフェースを提供しています。

まとめ

本PRは、既存のアーキテクチャを大きく変えることなく、内部ロジックの分離とシンプルなパス変数の追加によってセルフホスティングを実現した変更です。getIconFolder() の公開により、setIconPath() では対応できない高度なユースケース(バージョンクエリパラメータの付与など)にも、同じロジックを再利用したカスタムリゾルバーで対応できる拡張性が確保されています。

記事メタデータ

Generated by:
Claude Sonnet 4.6 for DiffDaily
LLM Trace:
d6eba44d

この記事はAIによって自動生成されています。内容の正確性については、必ずソースコードやPRを確認してください。

品質レビュー結果

Review Status:
承認済み
Review Count:
1回
Reviewed by:
Gemini 2.5 Pro for DiffDaily

Review Criteria:

記事構成 ✓ PASS

Title, Context, Technical Detailの存在と明確さ

「リード文→背景→技術詳細→設計判断→まとめ」の構成が明確で、ガイドラインに完全に準拠しています。

カスタムMarkdown構文 ✓ PASS

シンタックスハイライト・GitHubリンク記法の正確性

ファイル名付きシンタックスハイライトとGitHubリンク記法(PR, Issue)が正しく使用されています。

対象読者への適合性 ✓ PASS

エンジニア向けの適切な技術レベルと表現

ライブラリのカスタマイズを行うエンジニアという対象読者に対し、適切な技術レベルと情報量で記述されています。

パラグラフ・ライティング ✓ PASS

トピックセンテンス・1段落1トピック・段落長

各セクションの構成が論理的であり、各パラグラフはトピックセンテンスで始まり、1段落1トピックの原則が守られています。可読性が非常に高いです。

Diff内容との照合 ✓ PASS

コードブロックとDiff内容の一致

記事内で引用されているすべてのコードブロックは、提供されたDiff情報と正確に一致しています。

技術用語の正確性 ✓ PASS

技術用語の正確な使用

「リゾルバー」「フォールバック」「モジュールスコープ」などの技術用語が文脈に応じて正確に使用されています。

説明の技術的正確性 ✓ PASS

技術的主張の正確性と論理性

コード変更の目的と結果に関する説明は、Diff内容と技術的に完全に整合性が取れています。

事実の突合 ✓ PASS

PR情報による主張の裏付け(ハルシネーション検出)

記事内のすべての主張(セルフホストの容易化、カスタムリゾルバーへの対応など)は、PRのTitle, Description, Diff内容によって裏付けられており、ハルシネーションは検出されませんでした。

数値・固有名詞の確認 ✓ PASS

PR番号・コミットID・バージョン等の正確性

PR番号(#2240)およびIssue番号(#1423)が正確に記載・リンクされています。

タイトル・説明との一致 ✓ PASS

記事タイトル・説明とPR内容の一致

記事のタイトルはPRの主題「Make self-hosting FA icons easier」を的確に反映しています。

外部知識の正確性 ✓ PASS

PRに記載のない外部知識(LTS、サポート状況など)の不使用

PR情報に記載のない外部知識(バージョンのサポート状況など)の追加はなく、提供された情報源に忠実です。

時間表現の正確性 ✓ PASS

時間表現がPR情報と一致しているか

過去の課題と今回の変更による解決策という時間的な前後関係が正確に表現されています。