2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Chrome拡張機能をゼロから作る方法【Manifest V3対応・2026年最新】

2
Posted at

はじめに

本業エンジニアをしながら、Chrome拡張機能「SaveSmart - AI Reading List」を個人開発しました。

この記事では、Chrome拡張機能をゼロから作る方法を、実際のコードと一緒に解説します。

この記事で学べること:

  • Chrome拡張機能の基本構造
  • Manifest V3の書き方
  • popup・background・content scriptの役割
  • 実際に動くコードの全体像

Chrome拡張機能の基本構造

最小構成はこの4ファイルです:my-extension/
├── manifest.json # 拡張機能の設定ファイル
├── popup.html # ポップアップのUI
├── popup.js # ポップアップの動作
└── icons/ # アイコン画像


manifest.jsonの書き方

manifest.jsonは拡張機能の「設定ファイル」です。

{
  "manifest_version": 3,
  "name": "My Extension",
  "version": "1.0",
  "description": "Chrome拡張機能のサンプル",
  "permissions": [
    "storage",
    "activeTab",
    "scripting"
  ],
  "action": {
    "default_popup": "popup.html",
    "default_icon": {
      "16": "icons/icon16.png",
      "48": "icons/icon48.png",
      "128": "icons/icon128.png"
    }
  },
  "background": {
    "service_worker": "background.js"
  }
}

Manifest V3の重要ポイント:

  • manifest_versionは必ず3にする
  • backgroundはservice_workerを使う(V2のscriptsは廃止)
  • activeTab権限でアクティブなタブの情報を取得できる

popup.htmlの書き方

ツールバーアイコンをクリックしたときに表示されるUIです。

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <style>
    body {
      width: 300px;
      padding: 16px;
      background: #1a1a2e;
      color: #e2e8f0;
      font-family: sans-serif;
    }
    button {
      width: 100%;
      padding: 10px;
      background: #4f46e5;
      color: white;
      border: none;
      border-radius: 8px;
      cursor: pointer;
      font-size: 14px;
    }
    #result {
      margin-top: 12px;
      font-size: 13px;
      color: #9ca3af;
      line-height: 1.6;
    }
  </style>
</head>
<body>
  <h2 style="margin:0 0 12px;font-size:16px;">My Extension</h2>
  <button id="save-btn">このページを保存</button>
  <div id="result"></div>
  <script src="popup.js"></script>
</body>
</html>

popup.jsの書き方

document.addEventListener('DOMContentLoaded', () => {
  document.getElementById('save-btn').addEventListener('click', handleSave);
});

async function handleSave() {
  const [tab] = await chrome.tabs.query({ active: true, currentWindow: true });
  
  const results = await chrome.scripting.executeScript({
    target: { tabId: tab.id },
    func: () => document.body.innerText.slice(0, 1000)
  });
  
  const pageText = results[0].result;
  
  const { items = [] } = await chrome.storage.local.get(['items']);
  const newItem = {
    id: Date.now(),
    title: tab.title,
    url: tab.url,
    text: pageText,
    savedAt: new Date().toISOString()
  };
  
  await chrome.storage.local.set({ items: [newItem, ...items] });
  
  document.getElementById('result').textContent = '保存しました!';
}

background.jsの書き方

background.jsはバックグラウンドで動くService Workerです。

chrome.runtime.onInstalled.addListener(() => {
  console.log('拡張機能がインストールされました');
});

chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
  if (message.type === 'GET_DATA') {
    sendResponse({ data: 'レスポンスデータ' });
  }
  return true;
});

Manifest V3のハマりポイント:
Service WorkerはページをまたいでDOMにアクセスできません。DOMの操作はcontent scriptで行う必要があります。


content.jsの書き方

まずmanifest.jsonに追加:

"content_scripts": [
  {
    "matches": ["<all_urls>"],
    "js": ["content.js"]
  }
]

content.js:

chrome.runtime.sendMessage({
  type: 'PAGE_TITLE',
  title: document.title
});

chrome.runtime.onMessage.addListener((message) => {
  if (message.type === 'HIGHLIGHT') {
    document.body.style.border = '3px solid #4f46e5';
  }
});

Chromeへのインストール方法

開発中の拡張機能をChromeにインストールする方法:

  1. chrome://extensions/ を開く
  2. 右上の「デベロッパーモード」をオンにする
  3. 「パッケージ化されていない拡張機能を読み込む」をクリック
  4. 拡張機能のフォルダを選択

Chrome Web Storeへの申請方法

  1. Chrome Web Store Developer Dashboard にアクセス
  2. 開発者登録(5ドルの一回払い)
  3. 拡張機能をzip圧縮してアップロード
  4. スクリーンショット・説明文を入力して申請

審査は通常1〜3営業日かかります。


よくあるエラーと解決策

① Content Security Policy エラー

Refused to execute inline script because it violates the following Content Security Policy directive

解決:HTMLにonclick等のインラインイベントを書かない。全部JSファイルに書く。

② CORSエラー

Access to fetch at 'https://...' has been blocked by CORS policy

解決:バックエンド側にCORSヘッダーを追加する。

③ Service Worker が動かない
Manifest V3のService Workerは非常駐です。タイムアウトするので、長時間の処理は避けてメッセージパッシングで対応します。


実際に作ったもの

この記事の知識を使って「SaveSmart - AI Reading List」を作りました。

  • ワンクリックでWebページを保存
  • Claude APIでAI自動要約
  • Cloudflare WorkersでバックエンドAPI
  • Stripeで月額500円のサブスク決済

技術スタックの詳細はこちら:
https://zenn.dev/zmgt362/articles/ed9b17a1c99303

サービスはこちら:
https://savesmart-api.zmgt362.workers.dev


まとめ

Chrome拡張機能の基本構造:

  • manifest.json:設定ファイル
  • popup.html/js:UIと動作
  • background.js:バックグラウンド処理
  • content.js:ページ上での処理

Manifest V3のポイント:

  • インラインスクリプト禁止
  • Service Worker必須
  • CORSに注意

ぜひ自分の拡張機能を作ってみてください!

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?