【超基礎】Chrome拡張機能の作り方ハンズオン:version 3
はじめてGoogle Chrome拡張機能を開発しようというかたへ。
以下4ステップ、カンタンな機能からスタートして少しずつ機能追加しながら実際に作っていくことで「基本中の基本をおさえよう」という記事です。
- まず、最低限で動くchrome拡張機能を作る
- 拡張機能ポップアップ上でのみ動く(開いているWebページには作用しない)最小機能を追加する
- 開いているWebページに作用する最小機能を追加する
- 2と3を連携させる
(=Webページ上の情報を取得して拡張機能ポップアップ上に転記する)
具体的には、④で以下のように拡張機能ポップアップ上のボタンをクリックするとwebページの特定テキストをテキストエリアに転記する、というものが出来上がります。
正直何の役にも立たない拡張機能ですが、1→2→3→4と順番に進めることで、chrome拡張機能に必要な基本コンポーネントがイメージできるようになるはず。
結果的に、アイデア次第でchrome拡張機能でできることが増えそうな予感がしてくると思います。
ガチ知識ゼロから最初の一歩として、本記事の内容が役立てば嬉しいです。
- 「background.js(background service worker)の使いかたを知りたい」という方がいたらごめんなさい。本記事ではbackground.jsは使いません
- manifest verson 3の仕様で作ります
(ver.2が古い・ver.3が新しい)
ー もくじ ー
chrome拡張機能の開発 基礎となるテンプレートの準備
まず、chrome拡張機能アイコンをクリックしたら「HELLO WORLD」と表示されるだけ、「これ以上はカンタンにならない」というミニマム拡張機能を作ります。
以下ステップ1・2が面倒だというかたは、必要なファイルをコチラからZIPでダウンロードできるので、解凍してchromeインポートに使ってください。
1. デスクトップにフォルダ作成
デスクトップでなくてもいいですが、chrome拡張機能のソースコードをまとめて格納するフォルダを作っておきます。
今回の例では、「chrome-basics」というフォルダ名にしています。
2. manifest.json、popup.html を作成・編集
1で作成したフォルダ内に、manifest.json とpopup.htmlの2ファイルを作成します。
メモ:
- manifest.jsonのファイル名は、"manifest"でなければいけない
- popup.htmlのファイル名は"popup"ではなく何でもOK。manifest.jsonでファイル名指定を忘れずに
単純に、拡張機能アイコンをクリックした時にポップアップ表示されるので分かりやすさのためにpopup.htmlとしています。
作成したら、それぞれのファイルに以下をコピペします。
manifest.json{
"name": "HELLO WORLD",
"description": "chrome拡張機能の基礎",
"version": "1.0",
"manifest_version": 3,
"action": {
"default_popup": "popup.html"
}
}
上記"manifest_version"にあるとおり、バージョン3で作成しています。chrome拡張機能はバージョンが異なるとmanifest.jsonの記述方法が変わり、それだけでエラーになり動かなくなるので要注意。
popup.html<html>
<body>
<h1>HELLO WORLD</h1>
</body>
</html>
これで超・最低ラインをクリアしたchrome拡張機能が完成。
manifest.jsonとは、「manifest = 明らかにする・表明する」と意味するとおり、拡張機能全体の設定ファイルのようなものです。
上記例では、拡張機能の名前・説明・バージョン・拡張機能アイコンをクリックした時に表示されるHTMLを定義しています。
3. chrome拡張機能をchromeにインポート
chrome拡張機能ページへ行ったら、右上にある「デベロッパーモード」をオンにしたあと「パッケージ化されていない拡張機能を読み込む」をクリック。
ファイルの入ったフォルダを選択します。
すると、HELLO WORLD拡張機能がchromeにインポートされます。
ブラウザ右上の拡張機能マークをクリックし、ピン留めしておきます。
HELLO WORLD拡張機能がURLバー右端に常時表示状態になるので、「H」アイコンをクリックして「HELLO WORLD」と表示されれば完了です!
ここまでで、以下ステップ①が完了です。
- 最低限で動くchrome拡張機能をまず作る
- 拡張機能ポップアップ上でのみ動く(開いているWebページには作用しない)最小機能を追加する
- 開いているWebページに作用する最小機能を追加する
- 2と3を連携させる
(=Webページ上の情報を取得して拡張機能ポップアップ上に転記する)
次は、ステップ②の「拡張機能内で動く最小機能追加」です。
chrome拡張機能ポップアップ内で動作する最小機能の追加
ここで「拡張機能ポップアップ内で動作する」とはどういうことを意図しているかというと、
- 拡張機能アイコンをクリックしたときに表示されるちいさなポップアップ上で完結する機能
...ということです。
より具体的には、popup.htmlにpopup.jsを読み込ませて処理を追加します。
ゴールは、以下のようにポップアップ上のボタンを押したらポップアップ上のテキスト書き変えができるようになることとします。
具体的に、4ステップ。
- popup.js を作成
- popup.htmlを編集
- popup.jsにテキスト変更処理を追加
- chrome拡張機能を再読み込みして動作確認
それではひとつずつ順番に。
1. popup.js を作成
2. popup.htmlを編集
popup.htmlにボタン要素を追加記述し、popup.jsを読み込ませます。
popup.html<html>
<body>
<h1>HELLO WORLD</h1>
<button id="btn">text change</button>
<script src="popup.js"></script>
</body>
</html>
3. popup.jsにテキスト変更処理を追加
新たに作成したpopup.jsに、ボタンを押したらテキスト「HELLO WORLD」が書き変わるイベントリスナーを設定します。
popup.jsdocument.getElementById('btn').addEventListener('click', () => {
document.querySelector('h1').textContent = "CHANGED !!";
})
4. chrome拡張機能を再読み込みして動作確認
拡張機能ページのリロードマークをクリックすると、ここまでに行った修正が反映されます。
chrome拡張機能をクリックするとポップアップ画面にボタンが表示されているので、クリックしてテキストが変われば成功です。
動作しない?と思ったら:エラーを確認
「何かがおかしいかも」と思ったら拡張機能ページに「エラー」の表示がないかを確認しましょう。
ここで具体的にどこが原因でエラーになっているかが分かります。
ここまでのまとめ
- popup.htmlの中でJavaScriptを読み込ませることで、popup.html内に影響を与える処理を追加することができる
...ということがつかめればOKです。
ここまでで、以下ステップ②が完了です。
- 最低限で動くchrome拡張機能をまず作る
- 拡張機能ポップアップ上でのみ動く(開いているWebページには作用しない)最小機能を追加する
- 開いているWebページに作用する最小機能を追加する
- 2と3を連携させる
(=Webページ上の情報を取得して拡張機能ポップアップ上に転記する)
次は、ステップ③の「開いているWebページに作用する機能を追加」です。
Webページに作用する機能を追加する
ここで「Webページに作用する」とはどういうことを意図しているかというと、
- 拡張機能をインストール・有効化した状態で特定のWebページを開くと、そのWebページ上に要素を追加したり書き換えたりする
...ということです。
ゴールは、chrome拡張機能にcontent.jsを追加することで、https://qiita.com/のヘッダー上部にHELLO WORLDという文字列を埋め込みます。
具体的に、3ステップ。
- content.js を作成
- content.jsに要素追加処理を追加
- manifest.jsonでcontent.jsを読み込むよう設定
- chrome拡張機能を再読み込みして動作確認
それではひとつずつ順番に。
1. content.js を作成
ファイル名は"content"である必要はありません。
ステップ3でmanifest.jsonの中の"content_scripts:"でファイル名を指定することを忘れないように。
2. content.jsに要素追加処理を追加
content.jslet body = document.querySelector('body')
let addElement = document.createElement('h1');
addElement.textContent = 'HELLO WORLD';
body.prepend(addElement);
ここのコードは、今回対象とするhttps://qiita.com/のページ上に加える処理ならなんでもいいです。
簡易性を重視して、ただ単にテキスト追加処理としました。
3. manifest.jsonでcontent.jsを読み込むよう設定
以下、青マーカーをひいたところが追加部分です。
manifest.json{
"name": "HELLO WORLD",
"description": "chrome拡張機能の基礎",
"version": "1.0",
"manifest_version": 3,
"action": {
"default_popup": "popup.html"
},
"content_scripts": [
{
"js": ["content.js"],
"matches": ["https://qiita.com/*"]
}
]
}
content.js を qiita.com にアクセスしたときに読み込む、という設定をこれで追加できました。
4. chrome拡張機能を再読み込みして動作確認
ふたたび、chrome拡張機能を読み込み直してhttps://qiita.com/にアクセスしてみます。
ヘッダー上部に「HELLO WORLD」と表示されていればOK。
要チェック
ここまでのchrome拡張機能は、Qiita以外のサイトへアクセスしても「HELLO WORLD」は埋め込まれず機能しません。
その理由は、manifest.jsonで"content_scripts"の"matches"にQiitaのサイト内でしかcontent.jsを読み込まないように指定しているからです。
全サイトでcontent.jsを読み込ませる場合
"matches": ["<all_urls>"] と書くことで、全てのサイトで読み込むようになります。
ここまでのまとめ
manifest.jsonの中の"content_scripts"でJavaScriptを読み込ませることで、閲覧中のWebページに作用する処理を追加できる
ここまでで、以下ステップ③まで完了です。
- 最低限で動くchrome拡張機能をまず作る
- 拡張機能ポップアップ上でのみ動く(開いているWebページには作用しない)最小機能を追加する
- 開いているWebページに作用する最小機能を追加する
- 2と3を連携させる
(=Webページ上の情報を取得して拡張機能ポップアップ上に転記する)
次は、ステップ④の「拡張機能ポップアップとWebページの情報を連動させる」です。
chrome拡張機能ポップアップとWebページを連動させる
ここで「連動させる」とはどういうことを意図しているかというと、
- chrome拡張機能ポップアップ上のボタンを押すと、
- Webページのテキストを取得して、
- chrome拡張機能ポップアップ上のテキストボックスに転記する
...ということです。
具体的なゴールは、Qiitaトップページの1記事目のタイトルを、拡張機能ポップアップ上のテキストボックスに転記することとします。
この機能を実現するには、これまでとは違い、chrome拡張機能開発独自の概念「メッセージパッシング」をイメージできる必要があります。
事前知識:メッセージパッシング
「拡張機能ポップアップ上のテキストボックスにWebページ上の情報を取ってくる」
単純に考えると、popup.htmlで読み込んでいるpopup.jsの中に
document.querySelector('.xxx').textContent ...
などと書いてWebページ上のテキストを取ってくればいい、と考えがち。
ですが、popup.jsからWebページにコンテンツに直接アクセスすることはできません。
ではどのように拡張機能ポップアップ上にWebページの情報を持ってくるかというと、
popup.js から、Webページに作用できるcontent.js に"Webページ上の情報を送ってくれという指示"を出し、content.jsは指示に従い情報を取得、popup.jsに送り返す
...というふうにします。
popup.js←→content.js←→Webページ
の間でメッセージをやりとりする、というわけです。
ここまでイメージできれば、本記事ラストの機能追加ができるようになります。
以下、4ステップ。
- popup.html にテキストボックス・ボタン要素を追加
- popup.jsに処理追加(メッセージ送信)
- content.jsに処理追加(メッセージ受信 & 返信)
- chrome拡張機能を再読み込みして動作確認
ひとつずつ順番に。
1. popup.html にテキストボックス・ボタン要素を追加
popup.js<html>
<body>
<h1>HELLO WORLD</h1>
<input type="text" id="title">
<button id="btn">text change</button>
<button id="btn_get">get</button>
<script src="popup.js"></script>
</body>
</html>
2. popup.jsに処理追加(メッセージ送信)
popup.jsに以下をコピーして追記します。
popup.jsdocument.getElementById('btn_get').addEventListener('click', () => {
chrome.tabs.query( {active:true, currentWindow:true}, (tabs) => {
chrome.tabs.sendMessage(tabs[0].id, {message: 'getname'}, (content) => {
if(!content){
alert('Cannot Get! Try Reload First!');
return;
}
document.getElementById('title').value = content
});
});
});
- getボタンを押したらcontent.jsにメッセージ(指示)を送る
- 受け取ったコンテンツをテキストボックスへ入力
(コンテンツを受け取れなかったらアラート表示)
という処理をおこなっています。
3. content.jsに処理追加(メッセージ受信 & 返信)
content.jsに以下をコピーして追記します。
content.jschrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
let title = document.querySelector('.css-1fhgjcy').textContent
sendResponse(title);
});
- popup.jsから指示を受け取ったらWebページからタイトルテキストを取得
- 取得したテキストをpopup.jsに送り返す
という処理をおこなっています。
querySelectorで指定しているセレクタでは動かない可能性があるので、qiita.comでデベロッパーツールを使って確認してください。
4. chrome拡張機能を再読み込みして動作確認
chrome拡張機能を読み込み直してQiitaにアクセス。
getボタンをクリックしてWebページからタイトルが取得できればOKです。
ここまでのまとめ
拡張機能ポップアップ上とWebページ上を連動させるには「メッセージパッシング」をする。
これでチュートリアルは全て終わりです。
popup.js・content.jsにどんな処理を書くかによって、構想は無限大。
総まとめ:chrome拡張機能開発のカギはメッセージパッシング
これまでの内容を、簡潔にまとめました。
- 最小構成は、popup.html と manifest.json
- popup.htmlにpopup.jsを読み込ませると、popup.html上で動作するJavaScript処理を追加できる
- manifest.jsonにcontent_script(本記事ではcontent.js)を読み込ませると、Webページ上で動作するJavaScript処理を追加できる
- popup.js ー content.js間でメッセージをやり取りすることで、 Webコンテンツ(など)の情報受け渡しができる
おそらく、もっと調べていくとかならずぶち当たる壁が
- background または background.js
- background service worker (manifest version 3から登場した単語)
という概念の理解です(どれも同じ)。
ぼくは自分の目的にかなったchrome拡張機能をつくる上でbackgroundの理解まで不要だったため深掘りをしていませんが、リッチな拡張機能を作るためには以下のような相互にメッセージパッシングし合う処理が必要になってきます。
本記事通りにchrome拡張機能を最低機能から一通り作ってみると、Qiitaなどの他の解説記事が読みやすくなっているはずです。
参考Qiita:Chrome Extension の作り方 (その1: 3つの世界)
Google本家のドキュメントも置いておきます。英語が苦手でもgoogle翻訳拡張機能でページごと翻訳してしまえば問題なし。