以下では、DOMで動的にスクリプト(JavaScript)やスタイル(CSS)を読み込むための実践的方法を、仕組み・順序制御・エラーハンドリング・パフォーマンス・セキュリティまで含めて体系的に解説します。なお、説明文中では絵文字を使用しません。
1. 動的ロードの基礎
1.1 スクリプトの動的挿入(外部JS)
重要ポイント
-
innerHTMLで<script>を挿入しても、多くのブラウザで実行されません。必ずcreateElement('script')してDOMに挿入します。 -
動的に追加した
<script>は、読み込み完了順で実行されがちです(順序が崩れる)。順序固定は後述。
1.2 スタイルの動的挿入(外部CSS)
1.3 インラインスタイルの動的生成
2. 実行順序と依存関係
2.1 依存関係のある複数スクリプト
動的挿入した<script>は基本的に並行取得→到着順に実行されます。依存関係がある場合は、順次ロードにします。
-
deferはパーサ挿入時(HTML内に直書き)に効果的ですが、動的挿入では効果が限定的です。 -
ES Modules を使うなら、**動的
import()**も有効です(後述)。
2.2 ES Modules の動的読み込み(推奨)
依存解決をブラウザに任せられるため、モジュール時代は**import()**が便利です。
-
import()はPromiseを返すため、非同期制御が容易です。 -
事前に
<link rel="modulepreload" href="/js/feature.js">を置くと依存モジュールも先行取得でき、体感が改善する場合があります。
3. パフォーマンス最適化
-
遅延ロード: 使う直前まで読み込まない。
IntersectionObserverで要素が見えたら読み込み、requestIdleCallbackでアイドル時間に読み込みなど。 -
プリロード:
-
スクリプト:
<link rel="preload" as="script" href="..."> -
CSS:
<link rel="preload" as="style" href="...">→onloadでrel="stylesheet"に切り替える手法もある(FOUC対策を要検討)。
-
-
プリコネクト/ DNSプリフェッチ:
<link rel="preconnect" href="https://cdn.example.com">
<link rel="dns-prefetch" href="//cdn.example.com"> -
キャッシュ制御: バージョン付きクエリ(
?v=123)でキャッシュバスティング。逆に長期キャッシュ可能なファイルはimmutable戦略。 -
重複読み込みの防止:
data-keyやidで挿入済みかを判定。
4. エラーハンドリングとフォールバック
-
onerrorで代替CDNへ切替:
-
タイムアウトを設ける(上記実装例参照)。
-
CSSの失敗時も
onerrorで検知可能。必要なら代替テーマや簡易スタイルを適用。
5. セキュリティ(CSP / SRI / CORS)
-
CSP(Content Security Policy):
-
インライン
<style>や<script>を許可するにはnonceまたはhashが必要。サーバが発行するnonceをDOM挿入時に付与します。 -
外部リソースの読み込み先は
script-src/style-srcで許可ドメインに限定。
-
-
SRI(Subresource Integrity):
-
<script src="..." integrity="sha384-..." crossorigin="anonymous"> -
<link rel="stylesheet" href="..." integrity="sha384-..." crossorigin="anonymous">
改ざん検知に有効。crossoriginとセットで使うのが一般的。
-
-
URLのサニタイズ:
-
ユーザー入力をそのまま
src/hrefに使わない。ホワイトリスト方式で許可。
-
-
@importは避ける: CSS内の@importは遅く、CSPの観点でも管理が複雑になりがち。
6. スタイル適用の高度テクニック
6.1 CSSOM(insertRule/removeRule)
既存の<style>要素のシートを直接編集できます。
6.2 Constructable Stylesheets(adoptedStyleSheets)
パフォーマンスに優れ、Shadow DOMでも再利用しやすい手法です(未対応ブラウザがある点に注意)。
6.3 メディアクエリ・条件適用
6.4 代替スタイルシート(テーマ切替)
<link rel="alternate stylesheet" title="...">とdisabledプロパティを使い、テーマを切り替えできます。
7. よくある落とし穴
-
innerHTMLに<script>を書いても実行されない。必ず要素生成→DOM挿入。 -
動的
<script>の順序保証が崩れる。依存関係があるならasync=falseで逐次ロード、またはimport()で制御。 -
CSSはレンダリングに影響しうるため、遅延しすぎるとFOUT/FOUCが発生。重要CSSは早めに、非クリティカルは遅延。
-
何度も同じファイルを読み込むと副作用の重複(イベント多重登録等)。一意キーでの重複防止を徹底。
-
CSP/SRI設定と**
crossoriginの整合**が取れていないと読み込み失敗。
8. 実用レシピ集
8.1 ビューポートに入ったら地図SDKを後読み
8.2 モジュール機能をオンデマンドで読込
8.3 テーマを即時切替(Constructable Stylesheets + 変数)
8.4 クリティカルCSSはインライン、残りは遅延
9. アンロード(解除)とクリーンアップ
-
スクリプトはDOMから要素を削除しても実行済みコードは残るため、グローバル副作用(タイマー、イベント等)を自前で停止する必要があります。
-
CSSは<link>要素を削除するか、disabled = trueで無効化できます。インライン<style>は要素を削除。
10. まとめと指針
-
スクリプトはcreateElement(‘script’)または**import()**で、順序が必要ならasync=falseや逐次awaitで制御。
-
スタイルは<link rel=”stylesheet”>の動的追加、または<style>/CSSOM/Constructable Stylesheetsを使い分ける。
-
パフォーマンスは「必要な時だけ」「先読み」「重複防止」を徹底。
-
セキュリティはCSP・SRI・URLサニタイズを適用。
-
UXはFOUC対策、テーマ切替、条件適用を丁寧に。
ChatGPT5 生成日:2025/09/11