目次を表示する

Chrome拡張機能 2026

第7章 自作Chrome拡張による業務改善 ── 社内トイルを自分で倒す

第7章 自作Chrome拡張による業務改善 ── 社内トイルを自分で倒す


「既製品では届かない」トイルがある

市販のChrome拡張機能で解決できるトイルは多い。しかし「社内システム特有のUI」「独自の業務フロー」「チーム固有のルール」に由来するトイルは、既製品では対応できない。

自作Chrome拡張機能が解くべき問題は「社内にしか存在しないトイル」だ。

自作が正当化される条件:

✅ 既製品が存在しない(社内システム固有の問題)
✅ 毎日複数人が繰り返す操作である
✅ HTML + JavaScript で解決できる範囲の問題
✅ チームに展開できれば費用対効果が高い

❌ 自作が過剰なケース:
  既製品の拡張機能で解決できる
  1人しか使わない・週1回以下の操作
  バックエンドAPIの改修で根本解決できる

Chrome拡張機能の構造

自作に入る前に構造を理解する。

Chrome拡張機能の主要ファイル構成:

manifest.json           → 拡張機能のメタデータ・権限定義
content_scripts/
  content.js            → ページのDOMに直接アクセスする処理
background/
  service_worker.js     → バックグラウンド処理(イベントハンドリング)
popup/
  popup.html            → 拡張機能アイコンクリック時のUI
  popup.js
options/
  options.html          → 設定画面
icons/
  icon16.png / 48 / 128
// manifest.json の基本形
{
  "manifest_version": 3,
  "name": "社内PR共有ツール",
  "version": "1.0",
  "permissions": ["activeTab", "clipboardWrite", "storage"],
  "host_permissions": ["https://github.com/*"],
  "content_scripts": [{
    "matches": ["https://github.com/*/pull/*"],
    "js": ["content.js"]
  }],
  "background": {
    "service_worker": "service_worker.js"
  },
  "action": {
    "default_popup": "popup.html",
    "default_icon": "icons/icon16.png"
  }
}

実際の社内自作事例

事例1:PRレビュー指摘カウンター(ライトコード社)

問題: 大きなPRになると、レビューコメントへの対応漏れが発生する。「全コメントに返信したか」を目視確認するのが煩雑。

解決策: GitHubのPRページで指摘コメント数と解決済みコメント数をリアルタイムにカウントし、差分があれば背景を赤く警告表示する。

// content.js
function countComments() {
  // GitHubはTurboを使うためSPA的なページ遷移に対応が必要
  const totalComments = document.querySelectorAll(
    '.review-comment:not(.outdated)'
  ).length;

  const resolvedComments = document.querySelectorAll(
    '.review-comment.is-resolved'
  ).length;

  const badge = document.getElementById('review-counter-badge')
    || createBadge();

  badge.textContent = `${resolvedComments} / ${totalComments}`;

  // 未解決があれば警告色
  badge.style.backgroundColor =
    resolvedComments < totalComments ? '#dc2626' : '#16a34a';
}

// GitHubのSPA遷移に対応
window.addEventListener('turbo:load', countComments);
document.addEventListener('DOMContentLoaded', countComments);

効果:「指摘漏れによるマージ後の問題発生」がゼロに。レビュー完了の自信を持てるようになった。


事例2:PR→Slackリンク生成ツール(フォースタートアップス社)

問題: PRレビュー依頼時に「SlackにPRのURLとチケットURLをハイパーリンク形式で貼る」という操作を毎回手動で行っていた。

従来の手順(5ステップ):
  1. GitHubでPRのURLをコピー
  2. Slackのリンク作成画面を開く
  3. URLを貼り付けてテキストを入力
  4. LinearでチケットのURLをコピー
  5. 同様にSlackにリンクを作成

→ 毎回3〜4分かかっていた

解決策

// service_worker.js
chrome.contextMenus.create({
  id: 'copy-pr-link',
  title: 'PR情報をSlack形式でコピー',
  contexts: ['page'],
  documentUrlPatterns: ['https://github.com/*/pull/*']
});

chrome.contextMenus.onClicked.addListener(async (info, tab) => {
  if (info.menuItemId !== 'copy-pr-link') return;

  // PRのURL・タイトルを取得
  const result = await chrome.scripting.executeScript({
    target: { tabId: tab.id },
    func: () => ({
      title: document.querySelector('.js-issue-title')?.textContent.trim(),
      url: window.location.href,
      // チケット番号をPR本文から抽出(Linear等の命名規則に合わせる)
      ticketId: document.querySelector('.js-issue-title')
        ?.textContent.match(/([A-Z]+-\d+)/)?.[1]
    })
  });

  const { title, url, ticketId } = result[0].result;
  const ticketUrl = ticketId
    ? `https://linear.app/team/issue/${ticketId}`
    : null;

  // Slackのmrkdwn形式
  const slackText = [
    `<${url}|PR: ${title}>`,
    ticketUrl ? `<${ticketUrl}|チケット: ${ticketId}>` : null
  ].filter(Boolean).join('\n');

  await navigator.clipboard.writeText(slackText);
});

効果:「選択→右クリック→コピー→Slackに貼り付け」で完結。手動5ステップが2ステップになった。


事例3:社内ページのクイックナビゲーション

問題: 社内のBacklogやJira、ConfluenceのURLが複雑で毎回検索するか、ブックマークを探す必要がある。

解決策: 拡張機能のポップアップにクイックリンク一覧を表示し、ワンクリックでアクセス。

// popup.html
<!DOCTYPE html>
<html>
<head>
  <style>
    body { width: 300px; font-family: sans-serif; padding: 8px; }
    .link-item {
      display: block;
      padding: 8px;
      border-radius: 4px;
      cursor: pointer;
      text-decoration: none;
      color: #1f2937;
    }
    .link-item:hover { background: #f3f4f6; }
    .category { font-size: 11px; color: #6b7280; margin: 8px 0 4px; }
  </style>
</head>
<body>
  <div id="links"></div>
  <script src="popup.js"></script>
</body>
</html>

// popup.js
const LINKS = [
  { category: '開発', label: '今スプリントのボード', url: 'https://linear.app/...' },
  { category: '開発', label: 'PRレビュー待ち', url: 'https://github.com/pulls?q=...' },
  { category: '本番', label: 'Datadogダッシュボード', url: 'https://app.datadoghq.com/...' },
  { category: '本番', label: 'Sentry', url: 'https://sentry.io/...' },
  { category: 'ドキュメント', label: 'Architecture Doc', url: 'https://notion.so/...' },
];

// カテゴリごとにグループ化して表示

事例4:社内向けChrome拡張ストア(LINEヤフー社)

規模感の異なる取り組み

背景:
  LINEヤフー社内では、エンジニアが作った便利な
  Chrome拡張機能が多数存在していた。
  しかし配布がGitHub Enterprise経由のため、
  非エンジニアには使いにくかった。

解決策:
  社内向けのChrome拡張ストアページを構築。
  - 拡張機能をカテゴリ別に検索・閲覧
  - ワンクリックでインストール
  - バージョン管理・更新通知
  - レビュー・評価機能

学び:
  「エンジニアが作る → 全社員が使える」
  という流通経路を整備することで、
  Chrome拡張機能の業務改善効果が組織全体に広がる。

現代的な自作スタック

2025年の自作Chrome拡張は、フルスタックWebアプリと同じ技術スタックで書ける。

推奨スタック(2025年):

言語:TypeScript
UIフレームワーク:React(コンポーネント設計が可能)
ビルドツール:Vite(ホットリロード対応でDX高い)
スタイリング:Tailwind CSS
テスト:Vitest + Testing Library

プロジェクト作成:
  npx degit crxjs/vite-plugin-crx-template my-extension
  cd my-extension
  npm install
  npm run dev
  → Chromeに読み込み → コード編集 → 自動反映

AIコーディング支援:
  Claude Code / GitHub Copilot が Chrome拡張のコードを
  効率的に生成・補完できる。
  「このmanifest.jsonを見てcontent scriptを書いて」
  という指示でほぼ動くコードが出てくる。

自作の費用対効果の見積もり方

自作拡張を作る前に費用対効果を計算する。

計算式:

削減時間(分)= 1回の作業時間 × 1日の実行回数 × 利用人数
年間削減時間(h)= 削減時間(分)× 240日 ÷ 60

例:
  PRリンク作成(2分/回)× 5回/日 × エンジニア10人
  = 100分/日 = 400時間/年

開発コスト:
  エンジニア 1人 × 4時間(AIコーディング支援あり)

ROI:
  4時間の投資で 400時間を節約
  → 投資対効果 100倍

「4時間で400時間を節約できるなら、やらない理由がない」 というのが自作Chrome拡張のビジネスケースだ。