emahiro/b.log

Drastically Repeat Yourself !!!!

Chrome Extension に入門する

Overview

業務で Chrome Extension を使ってちょっとしたツールを実装する機会があったので備忘録としてまとめます。

基本的な作り方は以下のエントリを参考にさせていただきました。

r7kamura.com

Chrome Extension のいいところ

そもそも Chrome Extension を作ってみようと思った理由でもあるのですが、以下のような理由で作れると良いなと思いました。

  • Chrome を使ってさえいればブラウザ上で便利ツールを実装できることです。
  • ディレクトリ構成は JS と manifest ファイルさえあればいいので、余計なセットアップ等々も考慮することなく(ビルドプロセスとか)とりあえず動くものを実装できる。
  • 現職の場合、業務レベルではブラウザは Chrome が推奨なので Chrome 向けの対応さえしておけば簡単なツールは簡単に全社展開できること。(まぁ Chromium 使ってるブラウザであれば同様に対応できるので Firefox か Saferi を使っているユーザーでなければ対応できてしまいます)

かける労力に対して得られるアウトカムが思いの外大きいのは Chrome Extension のいいところかなと思いました。

基本的な実装の進め方

以下の公式のドキュメントを見つつ進めました。

developer.chrome.com

特に chrome のランタイムで必要な API を Call するときには permissions を設定する必要があるので都度権限が必要化を調べる必要があります。

いくつか触ってみた API

chrome.getURL

developer.chrome.com

local のファイルを取得するときもこれを使用します。

参考は以下

stackoverflow.com

URL を生成してそれを fetch で呼び出すので Promise が使えたりと便利です。これをするには manifest ファイルの web_accessible_resources にアクセスしたいファイルパスを予め定義しておく必要があります。

今回仕事で実装したツールについてはある条件においてリンクを別のリンクに張り替える(location.href を書き換える)というものだったので、そのマッピングデータを Extension で実装した local のデータファイルに定義しておいて、その定義ファイルを読み込む、ということをしていました。

サンプルは以下です。

  "web_accessible_resources": [
    {
      "resources": ["$pathToLocalFiles"],
      "matches": ["http://*/*", "https://*/*"]
    }
  ],

matches は Chrome Extension が動作する URL を正規表現で指定します。基本的にどの URL でも読み込みだけさせるには上記のような全公開的な正規表現にすればいいと思いますが、大体はドメインくらいは限定しておいたほうが良いかもしれません。

chrome.declarativeNetRequest

※ permission の設定が必要です。

ページをロードする(window.onload が走る)タイミングで動的になにかの処理を対象のページに施すことが出来ます。

ex. あるURL にアクセスされたら別の URL にリダイレクトしたりとか、あるURLのブロックをしたりとか。

どういった操作ができるのかは以下の公式ドキュメントを眺めるとなんとなくわかります。

developer.chrome.com

はまったところ

Manifest ファイルは V3 を利用する

ネット上で Chrome Extension の実装方法を探すと過去の実装方法をベースにしたものも多く見つかります。
パッケージ化しない(= 公開しない)ものであれば V2 も使って実装できるっぽい(エラーは出るけど)ですが、今回はちゃんとしたものを実装するために V3 をつかった 実装方法

Manifest では 実装した Extension が発火するページを制御できる

正規表現にマッチしたページのみで Chrome Extension を発火させることが可能です。

以下のドキュメントが詳しいです。

developer.chrome.com

Chrome Extension には Chrome 独自の module を使う

※ この module は import 宣言をせずとも実行環境が Chrome 上だと書くだけで動くので eslint 等を入れた場合 no-undef の警告に引っかかってしまいます。

そのため、eslint 等を導入する場合は no-use-before-define を off にしておく必要がありました。

以下がそのために追加した linter の定義ファイルです。

module.exports = {
  env: {
    browser: true,
    commonjs: true,
    es2021: true,
  },
  extends: 'airbnb-base',
  overrides: [
  ],
  parserOptions: {
    ecmaVersion: 'latest',
  },
  rules: {
    'no-restricted-globals': 0,
    'no-use-before-define': 0,
  },
};

Local の Debug がしづらい

これは仕方ないことですが、 local では Chromeエミュレーターを簡単に用意することは出来ないので、簡単なツールであれば実際に開発中のリポジトリChrome拡張機能にそのまま突っ込んで動作確認をしていました。

Chrome の設定から拡張機能を開いて上記のパッケージ化しないでアップロードする対象に manifest をルートとしてリポジトリをそのまま指定すれば Extension をインストールしたことになります。
拡張機能側でエラーが発生した場合もこの拡張機能一覧のページにエラーが発生したことが表示されるので、JS のエラー等々は確認できます。

まとめ

JS さえ使えて、かつパッケージ化しないクローズドな環境(社内限定とか)で使う Extension であれば、かなり簡単に Chrome Extension は実装、導入することが出来ました。
API もふんだんに用意されていて、結構自由度が高いのでこれからもなにか機会があれば Extension を実装して解決するようなアプローチをしていきたいなと思いました。

See Also

developer.chrome.com

qiita.com