`data-wa-preload` 属性でオートローダーにコンポーネントの事前読み込みを指定できるように
Web Awesome のオートローダーに data-wa-preload 属性のサポートが追加され、ページ初回表示時点で DOM に存在しないコンポーネントを事前に登録できるようになりました。これにより、動的に追加される Web Awesome コンポーネントの FOUCE(Flash of Undefined Custom Elements) を防止できます。
背景
既存のオートローダーは、ページのロード時に DOM を走査して Custom Elements を検出し、必要なコンポーネントを動的に登録する仕組みを持っています。しかし、JavaScript によってコンポーネントが動的に追加される場合、オートローダーの初回走査後に要素が挿入されるため、コンポーネントが未定義の状態で一瞬描画されてしまう問題がありました。この問題は #1501 で報告されており、ユーザーから「後から動的に追加する要素についても事前読み込みできる手段が欲しい」という要望が寄せられていました。
解決策として、HTML の属性を通じて「あらかじめロードすべきタグ名」を宣言できる仕組みが求められていました。JavaScript のコードを変更せず、マークアップ側で制御できる点が重要な設計要件となっています。
技術的な変更
autoloader.ts の discover 関数に、data-wa-preload 属性を持つ要素を収集するロジックが追加されました。
変更は packages/webawesome/src/utilities/autoloader.ts の discover 関数内、タグ名のユニーク化処理の直前に挿入されています。
追加されたコード:
// Collect tags from data-wa-preload attributes
const preloadSelectors = root.querySelectorAll('[data-wa-preload]');
const preloadRoots =
root instanceof Element && root.hasAttribute('data-wa-preload') ? [root, ...preloadSelectors] : preloadSelectors;
for (const el of preloadRoots) {
tags.push(
...(el as Element)
.getAttribute('data-wa-preload')!
.split(/\s+/)
.filter(tag => tag.startsWith('wa-')),
);
}
処理の流れは次のとおりです:
-
root.querySelectorAll('[data-wa-preload]')でdata-wa-preload属性を持つ全子孫要素を収集する -
root自身がElementかつdata-wa-preload属性を持つ場合は、rootも収集対象に含める - 各要素の属性値をスペース区切りで分割し、
wa-プレフィックスを持つタグ名のみを既存のtags配列に追加する - 既存の
[...new Set(tags)]によるユニーク化処理で重複が除去される
属性の値には、スペース区切りで複数のタグ名を列挙できます:
<div data-wa-preload="wa-dialog wa-drawer wa-tooltip">
<!-- 動的に追加されるコンテンツ -->
</div>
フィルタ条件として tag.startsWith('wa-') が適用されるため、不正な文字列や空白が属性値に混入しても、wa- プレフィックスを持たないものは無視されます。
設計判断
既存の discover 関数と tags 配列への統合という方式が採用されました。新たなローディング経路を追加するのではなく、DOM 走査で収集したタグ名と同じリストに追記し、その後のユニーク化・登録処理を共有する設計です。
root が Element の場合に root 自身も対象とする条件分岐は、discover が Document だけでなく任意の Element や ShadowRoot を引数に取れる汎用的なシグネチャを持つことへの配慮です。Document は hasAttribute を持たないため、root instanceof Element でガードしています。
また、wa- プレフィックスによるフィルタリングにより、属性値の検証を最小限のコストで行えます。専用のバリデーションロジックを設けず、既存の命名規則を利用した簡潔な実装といえます。
まとめ
data-wa-preload の追加は、HTML のマークアップで事前読み込みコンポーネントを宣言できるようにすることで、動的 UI を持つアプリケーションでの FOUCE 問題をオートローダーの既存の仕組みの延長線上で解決した変更です。コードの変更は最小限でありながら、discover 関数の汎用的なシグネチャや既存のユニーク化処理を活かした設計は、拡張への合理的なアプローチを示しています。