拡張機能の content script で module を使う
- カテゴリ:
- JavaScript
- コメント数:
- Comments: 2
◆ module の script タグを作って append
◆ 拡張機能内の JavaScript をロードするために web_accessible_resources の指定必要
◆ 拡張機能内の JavaScript をロードするために web_accessible_resources の指定必要
拡張機能と module
ブラウザ拡張機能は module 機能が出る前に作られたものなので module を考慮されていないものもありますmodule は HTML から JavaScript をロードするときに script タグに type="module" を指定する というものなので 普通に HTML を書く オプションやポップアップやその他の拡張機能で特別扱いされない任意のページなら問題ありません
バックグラウンド処理も本来はページが存在するので HTML で module として JavaScript をロードすれば問題ありません
ただ バックグラウンドの処理なのでほとんどの場合は HTML は不要で JavaScript のみで良いことから楽に書けるように一般的に知られてるのはこうなっています
"background": {
"scripts": ["bg.js"]
}
こうかけば自動で _generated_background_page.html という HTML が作られてそこに script タグが配置されて設定した JavaScript ファイルをロードしてくれます
module としてロードするなら
"background": {
"page": "bg.html"
}
とページを指定して その HTML に type="module" にした script タグを書けば良いです
そうなると残るはたぶん content script だけです
content script
content script は拡張機能の領域で動く他のとは違って 各ページ内で実行するものですバックグラウンドの処理から chrome.tabs.executeScript を使ってページ中でコードを実行したり manifest で設定した通りにページにコードを埋め込んだりできます
これは HTML を使うものではなく実行する JavaScript を指定して実行させるものです
なのでバックグラウンド処理のようには行きません
方法はコードを実行するページの document 中に type="module" の script タグを埋め込んで モジュールとして実行させるというものです
これだけで伝わる人には伝わると思いますが 一応簡単な例を作りました
例
構造- manifest.json
- loader.js
- content-script/
- index.js
- module1.js
- module2.js
manifest.json
{
"name": "content script",
"manifest_version": 2,
"version": "1",
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["loader.js"]
}
],
"web_accessible_resources": ["content-script/*"]
}
例なのでどのページでも実行させます
content script として実際に埋め込むファイルは loader.js です
これが script タグを作って module として本来ロードしたいモジュールファイルをロードさせます
ウェブページから拡張機能の JavaScript ファイルにアクセスすることになるので web_accessible_resources を使ってアクセス可能にします
loader.js
(() => {
const exid = chrome.runtime.id
const elid = exid + "-script"
if(document.getElementById(elid)) return
const scr = document.createElement("script")
scr.id = elid
scr.src = chrome.runtime.getURL("content-script/index.js")
scr.type = "module"
document.head.append(scr)
})()
一応二重ロードをしないようにしてますが バックグラウンドからページの更新イベントで実行するのではなく manifest で指定して実行する場合は pushState などで再実行されないと思うので別になくとも良いと思います
これで content-script/index.js が module としてロードされます
content-script/index.js
import module1 from "./module1.js"
module1()
content-script/module1.js
import module2 from "./module2.js"
export default () => {
console.log(1)
module2()
}
content-script/module2.js
export default () => console.log(2)
適当にページを開いてコンソールを開くと
12:49:51.230 1 module1.js:4
12:49:51.230 2 module2.js:1
モジュールが正常にロードされてますね
そろそろ module が使えるようになって結構経ちますし 拡張機能周りも module をデフォルトに移行してくれればいいのにと思います
ただ manifest_version 3 は web request の機能廃止とか言われてるのでその辺は不便になるのであまり変わってほしくない気持ちもあるんですよね
特定リクエストをブロックしたり CSS を自分で管理してるのにリダイレクトさせてカスタマイズしたテーマにしたりというのができなくなりますし