Chrome MV3拡張で Kuromojin を安定利用したい
Chrome 拡張(MV3)で日本語形態素解析を行う場合、Kuromoji / Kuromojin が便利です。しかし、MV3 の Service Worker から辞書を fetch すると、次のエラーがよく発生しました。
background.js:1 Kuromoji Error: TypeError: Failed to fetch
ここでは、MV3 の制約や fetch の仕組み を含めて、安定して Kuromojin を使う方法を詳しく解説します。
結構苦労したのでここに残します
1️⃣ fetch とは?
基本
fetch は JavaScript の組み込み API で、HTTP/HTTPS リクエストを送るために使います。
fetch("https://example.com/data.json")
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error(error));
非同期で動作する
Promise を返す
ブラウザ側でネットワーク接続を管理
fetch のよくある失敗原因
ネットワーク接続の問題
URL が間違っている(スペル、プロトコルなど)
CORS 制約でアクセスが拒否される
MV3 の Service Worker 内で制約に引っかかる
MV3 の Service Worker では、fetch が## 拡張内リソースや外部ファイルに対して失敗する## ことがあります。何度も失敗してとても大変でした。
2️⃣ MV3(Manifest V3)の特徴と fetch との関係
従来の MV2 との違い
項目 MV2 MV3
Background Script 常駐型 Service Worker 型(必要なときだけ起動)
fetch 制約 少なめ Service Worker 内では制限あり
セキュリティ 緩め CSP が強化、権限が限定
リソース使用 常駐 必要な時だけ起動 → 軽量化
Service Worker の制約
fetch がブラウザの通常コンテキストと異なる環境で動作
拡張内部リソース(辞書ファイル)を fetch すると Failed to fetch が発生しやすい
外部ネットワークでは CORS や CSP に引っかかる可能性もある
結論: Service Worker から辞書ファイルを fetch するのは不安定
3️⃣ Failed to fetch が起きる理由(MV3 + fetch)
fetch はリクエストを送信してレスポンスを待つが、Service Worker 内では一部制限がある
拡張内リソース(dict/*.json など)を Service Worker から直接読み込もうとすると失敗
ネットワークの問題ではなく、MV3 の設計による制約
4️⃣ 解決策:Content Script で fetch を実行
基本の仕組み
[Content Script] → fetch + Kuromojin 初期化 + 形態素解析 + ローマ字変換
│
▼
[Background Script (Service Worker)] ← 解析結果のみ受信
メリット
Content Script は ウェブページのコンテキストで動く → fetch 制限なし
拡張内リソースの fetch が安定
Service Worker は軽量で安定
5️⃣ プロジェクト構成例
my-extension/
├─ manifest.json
├─ background.js ← Service Worker
├─ content.js ← Content Script
├─ dict/ ← Kuromojin 辞書
└─ package.json
6️⃣ manifest.json 設定例
{
"manifest_version": 3,
"name": "Kuromojin MV3 Example",
"version": "1.0",
"background": { "service_worker": "background.js" },
"content_scripts": [
{ "matches": ["<all_urls>"], "js": ["content.js"] }
],
"web_accessible_resources": [
{ "resources": ["dict/*"], "matches": ["<all_urls>"] }
],
"permissions": ["scripting", "activeTab"]
}
web_accessible_resources に辞書ファイルを登録 → Content Script で fetch 可能
Content Script 内で fetch すると Service Worker の制約を回避可能できる
7️⃣ Content Script 実装例(fetch + Kuromojin)
import kuromojin from "kuromojin";
async function analyzePage() {
const text = document.body.innerText;
try {
// Kuromojin 初期化(内部で fetch が走る)
const tokens = await kuromojin.tokenize(text);
const romaji = tokens.map(t => convertToRomaji(t.surface_form));
// Background に送信
chrome.runtime.sendMessage({
type: "ANALYZED_TEXT",
data: romaji.join(" ")
});
} catch (e) {
console.error("fetch または Kuromojin 初期化エラー:", e);
}
}
function convertToRomaji(japanese: string): string {
// wanakana を使うと精度向上
return japanese;
}
analyzePage();
Content Script はページコンテキストで動くため fetch が安定
Kuromojin の内部 fetch も問題なし
これに少し苦戦した…
8️⃣ Background Script 実装例
chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => {
if (msg.type === "ANALYZED_TEXT") {
console.log("ローマ字変換済みテキスト:", msg.data);
}
});
Service Worker は解析をせず、軽量で安定!
fetch によるエラーはほぼ発生しない(はず…)
9️⃣ 注意点!
-
辞書ファイルは web_accessible_resources に登録
-
Content Script で fetch + Kuromojin 初期化
-
非同期処理で大規模ページも安定
4. ローマ字変換は wanakana などで精度向上!
- Service Worker は解析や fetch を避け、軽量化
10️⃣ まとめ
MV3 の Service Worker は fetch が不安定
Content Script に fetch + Kuromojin 初期化を移すことで安定化
Background Script は解析済み結果のみ受け取る
manifest.json の設定と辞書ファイル配置が重要
私は今とある拡張機能を作っているのですがここまでこれに苦戦するとは思いませんでした。これの他にも実は結構エラーも出ているので一旦全体の設計を見直そうかとも考えています。typescriptをもっと勉強しなくては……