Chrome 拡張 作り方

Chrome 拡張を作る手順をまとめておく


tl;dr

  • npm init vite@^2
  • npm i @crxjs/vite-plugin -D
  • JS を書く

作りたいもの

タイプした単語(英数字のみ)が特定の単語にマッチした場合に警告する拡張を作る。

参考にした記事

まずは公式。

Welcome - Chrome Developers

さっと眺めてみたが、全くの初心者がこれをすべて読んでから開発を始めるのは厳しい。あまりにも時間がかかりすぎる。 なので、作りながらトライ・アンド・エラーを繰り返すことにした。必要な設定だったり副作用、制限などなどを把握するために適宜参照することになる。

Create a Vite-React Chrome Extension in 90 seconds - DEV Community

記事は 2021 年 12 月のものだが、紹介されている手順で全く問題なく作れる。 vite と @crxjs/vite-plugin を使って作っていく。

開発中の chrome 拡張は手でドラッグ・アンド・ドロップしてインストールするが、vite は hmr をサポートしており、インクリメンタルに開発できるのが良い。Chrome の developer tools でブレークポイントを仕掛けてのでバッグもできて DX も良い。

また最初から react で書くことができるのもありがたい。

vite は 2 系を使う

2022/11/23 現在、CRXJS は vite@^3 に対応していない。手順通りに vite@^2 をインストールしないとビルドできないので注意。

CRXJS doesn't yet work with Vite 3, but support is coming soon!

CRXJS とは

https://github.com/crxjs/chrome-extension-tools/tree/main/packages/vite-plugin

Chrome Extension を作るためのツール。

手順

基本的には先に紹介した記事の手順に沿ってやっていく。

vite のインストール

$ npm init vite@^2

Need to install the following packages:
  create-vite@^2
Ok to proceed? (y) y
✔ Project name: … eatinc
✔ Select a framework: › react
✔ Select a variant: › react-ts

Scaffolding project in /Users/nabetama/src/github.com/nabetama/eatinc...

Done. Now run:

  cd eatinc
  npm install
  npm run dev

案内されたとおりに、npm package をインストールする。

$ cd eatinc
$ npm install

crxjs/vite-plugin のインストール

$ npm i @crxjs/vite-plugin -D

ここまでやると以下のようなファイル構成になるはず。

$ git status
On branch main

No commits yet

Untracked files:
  (use "git add <file>..." to include in what will be committed)
        .gitignore
        index.html
        package-lock.json
        package.json
        src/
        tsconfig.json
        tsconfig.node.json
        vite.config.ts

@types/chrome 入れる

chrome の型定義ファイルを入れないと、tsc 怒られるので入れる。

$ npm i -D @types/chrome

prettier 入れておく

スタイルをめぐる継続的な論争を引き起こさないよう、prettier を入れておく。

公式参照.

vite の設定と manifest.json を書く

manifest.json

{
  "manifest_version": 3,
  "name": "eatinc",
  "version": "0.0.1",
  "action": { "default_popup": "index.html" }
}

vite.config.ts

import { defineConfig } from "vite"
import react from "@vitejs/plugin-react"
import { crx } from "@crxjs/vite-plugin"

import manifest from "./manifest.json" assert { type: "json" }

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [react(), crx({ manifest })],
}

ビルドしてみる

この時点で一度 npm run dev してみる。

$ npm run dev

> [email protected] dev
> vite


  vite v2.9.15 dev server running at:

  > Local: http://localhost:3000/
  > Network: use `--host` to expose

  ready in 341ms.

11:04:17 AM [crx] files start dist
11:04:17 AM [crx] files ready in 166ms

こんな感じでサーバーが立ち上がり、/dist 以下にファイルが作られているはず。

$ pwd
/Users/nabetama/src/github.com/nabetama/eatinc
$ la dist
total 24
drwxr-xr-x  17 nabetama  staff  544 Nov 23 11:04 ../
-rw-r--r--   1 nabetama  staff  216 Nov 23 11:04 manifest.json
-rw-r--r--   1 nabetama  staff   91 Nov 23 11:04 service-worker-loader.js
drwxr-xr-x   8 nabetama  staff  256 Nov 23 11:04 ./
-rw-r--r--   1 nabetama  staff  389 Nov 23 11:04 index.html
drwxr-xr-x   3 nabetama  staff   96 Nov 23 11:04 node_modules/
drwxr-xr-x   3 nabetama  staff   96 Nov 23 11:04 vendor/
drwxr-xr-x   6 nabetama  staff  192 Nov 23 11:04 assets/

先に紹介した記事の通り、chrome にインストールしてみる。

chrome://extensions/ を開き、右上の「デベロッパーモード」をアクティブにし、作成された dist ディレクトリをドラッグ・アンド・ドロップすればインストールできる。

ブラウザに拡張のアイコンを表示させ、クリックすると http://localhost:3000 と同じ内容が表示される。

これで動作確認は OK.

基本的に npm run dev しておけば良い。コードを更新すればブラウザにインストールした拡張にも反映される(What is CRXJS)。

keypress イベントを監視する JS を書く

https://github.com/nabetama/eatinc/blob/main/src/handler/keyEventHandler.ts

  • 入力した文字列を N 文字保持する
  • N 文字の中に特定の単語 W が含まれていた場合に alert を出す
  • W は複数登録可能

manifest.json を以下のように修正する。

{
  "manifest_version": 3,
  "name": "eatinc",
  "version": "0.0.5",
  "action": { "default_popup": "index.html" },
  "permissions": ["tabs", "storage"],
  "host_permissions": ["*://github.com/"],
  "content_scripts": [
    {
      "matches": ["https://github.com/*"],
      "js": ["src/handler/keyEventHandler.ts"],
      "run_at": "document_start"
    }
  ],
  "icons": {
    "128": "public/128.png"
  }
}

どんな設定を追加すれば良いか、全くわからなかったのでトライ・アンド・エラーで試行錯誤した。 たとえば、permissions"storage"chrome.storage を利用するための必須設定だが、これを書かないと、chrome.storage が undefined になりアクセスできなかったりする。

Chrome の manifest のドキュメントを適宜参照しつつ、この形に落ち着いた。

アイコン

アイコン は icon-monoから悪徳警官のアイコンを選んだ。

単語登録画面

chrome.storage.local に単語を保存するコードを書く。

https://github.com/nabetama/eatinc/blob/main/src/App.tsx

画面はどこに用意するのが良さそう…?

Chrome 拡張で設定画面的な UI を作るとなると、以下のいずれかにページを用意するようだった。

正解はなさそうだが最適解もわからないので階層の浅い前者を採用した。index.html を書く。

Imgur

余談:react たまに書くが、そのたびに知らないことが増え続けている…。

tips

デバッグの類

npm run dev していれば柔軟なデバッグができる。

ポップアップのデバッグ

ツールバーに並んでいる拡張のアイコンをクリックしたときの画面(ポップアップ)をデバッグしたいときがあると思う。 そういうときは拡張のアイコンを右クリックし、「ポップアップを検証」をクリックすれば Chrome の Developer tools を利用してのデバッグが可能だ。 ブレークポイントを使うことももちろん可能。

バックグラウンドで実行している JS のデバッグ

普通に Chrome Developer tools が使える。

完了

長かった。お疲れさまでした。

vite と @crxjs/vite-plugin のおかげで、コードを書くことだけに集中できるのは助かる。

なお、ストアに公開する場合は Developer 登録料が $5 かかります