content-script-developer について
ページ状態の読み取りや UI 注入を行うブラウザー拡張機能のコンテンツスクリプト開発スキルです。安全で冪等な処理と、メインスレッドを妨げない動的ページ対応を重視します。
主な機能
- 01安全な UI 注入
- 02スタイル分離と Shadow DOM
- 03SPA と DOM 変更への対応
- 04MutationObserver のスロットリング
- 05バックグラウンド通信とストレージ
活用シーン
- 01サードパーティーページへの拡張 UI 追加
- 02動的な Web ページ状態の読み取り
- 03SPA 遷移後の UI 重複防止
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ shipshitdev/ skills --skill content-script-developerインストール後、Claude Code で/content-script-developerを入力して読み込まれたか確認します。
同梱ファイルplugin.json
詳細
コンテンツスクリプト開発者
使用する場面
- コンテンツスクリプトを作成または更新するとき
- サードパーティのページに UI を挿入するとき
- ブラウザー拡張機能でページの状態をスクレイピングまたは読み取るとき
- SPA のナビゲーション変更や動的な DOM の更新を処理するとき
主な制約
- コンテンツスクリプトは分離された世界で実行されるため、ページの JS スコープは共有されません。
- ホストページを汚染しないようにします(グローバルスタイル、競合する ID/クラス)。
- 冪等性を確保します。再実行時に挿入が重複しないようにします。
- 壊れやすいクラスの連鎖より、堅牢なセレクターを優先します。
- メインスレッドをブロックしないでください。オブザーバーとイベントハンドラーをスロットリングします。
ワークフロー
1) 対象ページを把握する
- 安定したアンカー(data 属性、ID、ランドマークロール)を特定します。
- SPA のナビゲーションパターン(URL の変更、DOM ルートの置き換え)を確認します。
- 必要な処理を決めます。読み取り専用のスクレイピングか、UI の挿入かを判断します。
2) 安全な挿入を計画する
- UI 用のルートコンテナを 1 つ作成します。
- CSS の競合が起こりそうな場合は、シャドウルートを使用します。
- 固有のプレフィックスを付けるか、ルート内にスコープを限定してスタイルを追加します。
- ページがルートを置き換えた場合に備えて、クリーンアップ用のフックを用意します。
3) 動的なページに対応する
- DOM の変更には
MutationObserverを使用します。 requestAnimationFrameまたはデバウンスを使って処理をスロットリングします。- ナビゲーションイベント時にアンカーを再確認します。
4) データを送信・保存する
- バックグラウンド/サービスワーカーの呼び出しには
chrome.runtime.sendMessageを使用します。 - 永続状態には
chrome.storageを使用します。 - トークンや機密データは DOM ではなく、拡張機能のストレージに保存します。
5) アクセシビリティと UX
- UI 要素はキーボードでフォーカスできるようにします。
- フォーカススタイルを視認できるようにします。
- コントロールに ARIA ラベルを設定します。
パターンとスニペット
冪等な UI の挿入
const ROOT_ID = 'ext-root';
export function ensureRoot() {
let root = document.getElementById(ROOT_ID);
if (root) return root;
root = document.createElement('div');
root.id = ROOT_ID;
root.setAttribute('data-ext-root', 'true');
document.body.appendChild(root);
return root;
}
安全なスタイル設定(スコープ限定)
const styleId = 'ext-style';
function injectStyles(css: string) {
if (document.getElementById(styleId)) return;
const style = document.createElement('style');
style.id = styleId;
style.textContent = css;
document.head.appendChild(style);
}
スロットリング付き MutationObserver
let scheduled = false;
const observer = new MutationObserver(() => {
if (scheduled) return;
scheduled = true;
requestAnimationFrame(() => {
scheduled = false;
// re-check anchors or update UI
});
});
observer.observe(document.body, { childList: true, subtree: true });
バックグラウンドへのメッセージ送信
async function fetchData(payload: Record<string, unknown>) {
return await chrome.runtime.sendMessage({ type: 'FETCH_DATA', payload });
}
信頼性チェックリスト
- UI の挿入が冪等である
- スタイルのスコープが限定されているか、シャドウルート内にある
- オブザーバーがスロットリングされ、適切にクリーンアップされている
- メッセージングで明示的なメッセージタイプを使用している
- ホストページのパフォーマンスが安定している
よくある落とし穴
- SPA のナビゲーション時に同じ UI を複数回挿入する
- わずかな DOM の変更で壊れるセレクターを使用する
- ホストページのスタイルを上書きするグローバル CSS
- スロットリングされていない、負荷の高い MutationObserver のハンドラー
メモ
- 大きな単発スクリプトより、小さく組み合わせ可能なヘルパーを優先します。
- 拡張機能のログにはプレフィックスを付け、本番環境で簡単に無効化できるようにします。
コメント
Markdown 対応