初期化スタイル3種と二重ロード耐性 — 命令的・data属性・Web Components を比較する
前記事までで、5製品の分離戦略・プロトコル契約・版管理を分解しました。今回は顧客が触る一番外側、「SDK をどう呼び出すか」の API 設計を扱います。5製品を並べると3スタイルに分かれます。
3スタイルの実装
2026-08-08 時点で各バンドルから抽出した初期化パターンです。
| 製品 | スタイル | 顧客が書くコード |
|---|---|---|
| YouTube | 命令的 (callback) | <div id="player"></div> + window.onYouTubeIframeAPIReady = () => new YT.Player("player", {...}) |
| Vimeo | 命令的 (constructor) | <div id="p"></div> + new Vimeo.Player("p", { id: 123 }) |
| Safie | 命令的 (namespace) | Safie.Player.embedInto(element, options) |
| Video.js | data 属性 (auto-scan) | <video data-setup='{"controls": true}'> (自動検出) |
| Mux Player | Web Components | <mux-player playback-id="..."></mux-player> |
命令的が3、data 属性が1、Web Components が1。それぞれ想定顧客のワークフローが違います。
順に見ます。
命令的 API: YouTube 型
<script src="https://www.youtube.com/iframe_api"></script> を貼ると、window に YT 名前空間が生えて、new YT.Player(id, config) で呼び出します。ただし SDK ロードが非同期なので、window に onYouTubeIframeAPIReady というグローバルコールバックを事前に定義しておく必要があります。
<div id="player"></div>
<script>
window.onYouTubeIframeAPIReady = function() {
new YT.Player("player", {
videoId: "M7lc1UVf-VE",
events: { onReady: onPlayerReady }
});
};
</script>
<script src="https://www.youtube.com/iframe_api"></script>
この設計は2010年頃の web API の書き方をそのまま2026年まで持ってきています。今から書くなら window.onYouTubeIframeAPIReady は使わず、Promise + 型定義が自然です。ただし YouTube はすでに膨大な既存埋め込みを抱えていて、API 破壊を出せません。
Vimeo は同じ命令的でも constructor 直接呼び出しの形で、ready を待つ必要がありません。
<iframe id="v" src="https://player.vimeo.com/video/76979871"></iframe>
<script>
const player = new Vimeo.Player("v");
player.play();
</script>
Vimeo は iframe を顧客側で書いてもらい、そこに new Vimeo.Player(iframe) を後付けする。iframe 生成のタイミングを顧客に委ねる分、SDK ロード完了を待つ callback が要らなくなります。
Safie は namespace パターンで、window.Safie = { Auth, Users, Devices, Player, UIControl, Config } を loader が生やします。実装では:
window.Safie = { Auth: wn, Users: Dn, Devices: _n, Player: xn, UIControl: zn, Config: Qn }
Safie.Auth.initialize(...) → Safie.Player.embedInto(element, ...) のような多段構造で、SDK の機能領域が広い(認証・デバイス管理・再生・UI 制御・設定)ことに対応した名前空間分割です。
data 属性: Video.js 型
Video.js は HTML 側に data 属性を書くだけで自動的にプレイヤーに変換します。
<video data-setup='{"controls": true, "autoplay": false}'>
<source src="movie.mp4" type="video/mp4">
</video>
<script src="https://vjs.zencdn.net/8.23.4/video.min.js"></script>
バンドル側の実装:
autoSetup) {
var e = Array.prototype.slice.call(document.getElementsByTagName("video"));
// data-setup を持つ video 要素を走査してプレイヤー化
}
DOM を自動スキャンする挙動なので、CMS (WordPress 等) や静的サイトジェネレータで JS を書きたくない環境に強いです。反面、SPA (React/Vue) では DOM が JS で動的生成されるため、data 属性が正しく認識される保証がなく、videojs(id, options) の命令的 API を併用することになります。
Web Components: Mux Player 型
Mux Player はカスタム要素を大量に定義しています。
customElements.define("media-airplay-button", ...)
customElements.define("media-audio-track-menu", ...)
customElements.define("media-captions-button", ...)
customElements.define("media-cast-button", ...)
// 他多数
顧客が書くコードは:
<mux-player
playback-id="qxb01i6T202018GFS02vp9RIe01icTcDCjVzQpmaB00CUisJ4"
metadata-video-title="Test"
></mux-player>
<script src="https://cdn.jsdelivr.net/npm/@mux/mux-player@3.7.0"></script>
Web Components なので React/Vue/Svelte のどれからでも「ただの HTML タグ」として使えます。SPA との親和性が高く、コンポーネント指向のフレームワークが主流の2020年代に自然な設計です。
トレードオフは、Web Components を理解しない古いブラウザ (IE11 等) が対象外になること、shadow DOM のスタイル境界を顧客が理解して使う必要があること、SEO クローラーで shadow DOM 内が index されない可能性があることです。今から新規に SDK を作るなら第一選択ですが、法人顧客の要件次第で命令的 API を追加提供する場合があります。
二重ロード問題
5製品すべての loader バンドルに、二重ロード対策のコードが入っています。「顧客が誤って同じ <script> タグを2回書く」「SPA でルート遷移のたびにロードしてしまう」「CMS プラグイン2つが同じ SDK を独立に読み込む」といった状況が実際に発生します。
命令的 API の場合 (YouTube):
if (!window["YT"]) YT = { loading: 0, loaded: 0 };
if (!YT.loading) {
YT.loading = 1;
// 実際のロード処理
}
window.YT の存在チェックで、2回目以降は初期化をスキップします。YT.loading フラグで「ロード中」と「ロード済み」も区別しています。
Web Components の場合 (Mux Player):
customElements.define("mux-player", ...) を同じ名前で2回呼ぶと、2回目で NotSupportedError 例外が投げられます。Mux Player の実装はこれをキャッチするか事前に customElements.get("mux-player") で確認するかのどちらかで対処します。命令的 API のフラグ管理と本質的に同じ問題が、Web Components の仕様で強制されるだけです。
data 属性の場合 (Video.js):
DOM スキャンが2回動くと、同じ video 要素が2回プレイヤー化されようとして壊れます。Video.js は要素に player_ プロパティを付けておいて、既にある要素はスキップします。副作用の冪等性を要素側に持たせる設計です。
自作するときの選び方
| 想定顧客 | 適した初期化スタイル | 二重ロード対策 |
|---|---|---|
| 静的 HTML / CMS ユーザー | data 属性 | 要素側フラグ (player_ 相当) |
| SPA (React/Vue) 開発者 | Web Components | customElements.get() 事前確認 |
| 古い既存埋め込みが多い | 命令的 (callback) | window.YOUR_SDK 存在チェック |
| 新規開発、多様な顧客 | Web Components + 命令的の両対応 | 上記2つ両方 |
スタイルを1つに絞ると API 表面が狭くなり、ドキュメント・テスト・互換性維持のコストが下がります。5製品はどれも1〜2種類に絞っています。全部提供する SDK は少ないです。想定顧客のワークフローを最初に決めて、そこから逆算して選ぶのが良い設計です。
次: 全部組み合わせて自分で作る
これで5つの spoke が揃いました。埋め込み形態(iframe / DOM 直挿し)、loader/body 分離、CSP と iframe 隔離、postMessage 契約、cache-control 戦略、初期化スタイル。次で最小の埋め込み SDK を端から端まで組み、6つの決断を実装で明示的に選び直します。
実測日は 2026-08-08。初期化 API は破壊的変更を出しにくいため長期安定します。二重ロード対策の実装は年単位で変わりません。
この記事は役に立ちましたか?