TypeScriptでChrome拡張を作ろう！

この記事は[コネヒト Advent Calendar 2020 - Qiita](https://qiita.com/advent-calendar/2020/connehito) 14日目の記事です。

# まえがき

個人的に一番使っているウェブブラウザはChromeなのですが、御存知の通りChromeには「Chrome拡張」というプラグインで更にChromeを便利にすることが出来ます。

「欲しい機能」を探すのも楽しいのですが、自分でChrome拡張を作ることで「学ぶ楽しみ・作る楽しみ」を味わうことが出来ます。

尖った技術ももちろん楽しい学びになるのですが、今回は前述の通り、普段使うブラウザを「自分でより使いやすく拡張する」技術にフォーカスしてお送りしようかと思います。
TypeScriptの説明よりもChrome拡張の設定ファイルである `manifest.json` の各項目の説明がメインになっているので、TypeScriptについてはKindle Unlimitedに無料で学習できる本もあるのでそちらも参考にしてみてください！

- [速習 TypeScript 第2版 速習シリーズ | 山田祥寛](https://www.amazon.co.jp/%E9%80%9F%E7%BF%92-TypeScript-%E7%AC%AC2%E7%89%88-%E9%80%9F%E7%BF%92%E3%82%B7%E3%83%AA%E3%83%BC%E3%82%BA-%E5%B1%B1%E7%94%B0%E7%A5%A5%E5%AF%9B-ebook/dp/B086JKVGPB/ref=sr_1_1?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&crid=GOEU5W8JGAQC&dchild=1&keywords=typescript&qid=1607858821&refinements=p_n_feature_nineteen_browse-bin%3A3169286051&rnid=3169285051&s=digital-text&sprefix=typesc%2Cdigital-text%2C557&sr=1-1)
- [速習 TypeScript: altJSのデファクトスタンダートを素早く学ぶ！ 速習シリーズ | 山田祥寛](https://www.amazon.co.jp/%E9%80%9F%E7%BF%92TypeScript-altJS%E3%81%AE%E3%83%87%E3%83%95%E3%82%A1%E3%82%AF%E3%83%88%E3%82%B9%E3%82%BF%E3%83%B3%E3%83%80%E3%83%BC%E3%83%88%E3%82%92%E7%B4%A0%E6%97%A9%E3%81%8F%E5%AD%A6%E3%81%B6%EF%BC%81-%E9%80%9F%E7%BF%92%E3%82%B7%E3%83%AA%E3%83%BC%E3%82%BA-%E5%B1%B1%E7%94%B0%E7%A5%A5%E5%AF%9B-ebook/dp/B0733113NK/ref=sr_1_3?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&crid=GOEU5W8JGAQC&dchild=1&keywords=typescript&qid=1607858821&refinements=p_n_feature_nineteen_browse-bin%3A3169286051&rnid=3169285051&s=digital-text&sprefix=typesc%2Cdigital-text%2C557&sr=1-3)



# 概要

Chrome拡張は主にJavaScriptの知識が必要になります。
逆に言うと「JavaScriptの知識があればChrome拡張を作ることが出来る」のです！


本稿ではChrome拡張を作るために必要なもの、一歩進んでChrome拡張をTypeScriptで作る方法について調べたこと、気付きなどを残しておこうと思います。

# 下準備

## Chrome拡張の基本構成

Chrome拡張はさまざまなクリエイターがChromeウェブストアでプラグインを公開していますが、自分で作ることも出来ます。
その際に必要なものを簡単に紹介します。

### manifest.json

まずは「そのChrome拡張がどういうものなのか？」を定義したマニフェストファイルが必要になります。
マニフェストファイルの詳細は[こちら](https://developer.chrome.com/docs/extensions/mv2/manifest/)を読んでみてください。

**「ハハッ！！英語分からん！」**

ってなると思うので他の方が書いたQiitaの記事をご覧になっていただくとともに、最低限必要な項目を簡単に紹介します。
[Chrome 拡張機能のマニフェストファイルの書き方 - Qiita](https://qiita.com/mdstoy/items/9866544e37987337dc79)

#### manifest_version
これは `2`, `3` のいずれかを設定します。
先日v3が公開されたので、新しいバージョンで作成する際にはこちらもご参考に！
https://developer.chrome.com/docs/extensions/mv3/intro/

#### name
Chrome拡張の名前を設定します。

#### description
Chrome拡張の説明です。この項目は省略可能です。

#### permissions
Chrome拡張内でChromeのどの機能にアクセス可能にするかを定義します。
https://developer.chrome.com/docs/extensions/mv2/declare_permissions/

私がよく設定しているものには以下のものがあります。

1. tabs<br />Chrome内で開いているタブ(=ページ)へのアクセス
2. clipboardWrite/clipboardRead<br />PCのクリップボードへの読み書き
3. storage<br />Chrome拡張内で設定したものをLocal/Cloudに保存する。<br />再度実行したときや、ポップアップ画面で設定した内容をバックグラウンドやcontent_scripts内で利用したいときに使います。

#### icons
Chrome拡張のアイコンです。
それぞれのサイズごとに使われるシーンが異なります。
https://developer.chrome.com/docs/extensions/mv2/manifest/icons/

#### version
Chrome拡張自体のバージョン番号です。
このバージョンはChromeWebストアに **新しいバージョンのものを公開する** ときにインクリメントして保存する必要があります。

#### background
バックグラウンドプロセスとしてChrome拡張を動かしたいときに、どのファイルを利用するかを定義するものです。
具体的には、ブラウザ内でのショートカットキーをハンドリングするときなどに利用します。

#### content_scripts
現在アクティブとなっているタブ(=ページ)内でのDOMの操作を行いたいときなどに利用するスクリプトファイルや設定を定義するものです。
https://developer.chrome.com/docs/extensions/mv2/content_scripts/

- matches<br />
  特定のサイトのみに適用したい場合に、URLを定義します。<br />
  ここではワイルドカードでの指定が可能です。
 https://developer.chrome.com/docs/extensions/mv2/match_patterns/
- css<br />
  content_scriptsを実行する際に追加してCSSを当てたい場合に定義します。
- js<br />
  実際のスクリプトファイルを定義します。
- run_at<br />
  どのタイミングでスクリプトを実行するかを定義します。<br />
  ここでは **document_idle(デフォルト)**, **document_start**, **document_end** を設定します。
- all_frames<br />
拡張機能で、JavaScriptファイルとCSSファイルを、指定したURL(前述の `matches`)に一致するすべてのフレームに挿入するか、タブの一番上のフレームにのみ挿入するかを `true / false` で指定できます。

#### browser_action
Chrome拡張をインストールするとURLバーの右横に追加したChrome拡張が追加されるのですが、その際のアイコンやタイトル、挙動などを定義します。
https://developer.chrome.com/docs/extensions/reference/browserAction/

#### commands
キーボードショートカットを最大4つまで定義することが出来ます。
https://developer.chrome.com/docs/extensions/reference/commands/
ユニークなコマンド名をキーとして定義します。

```json:コマンドの記述例
"commands": {   
    "close_duplicate_tabs": {
      "suggested_key": {
        "default": "Alt+W"
      },
      "description": "Close duplicate tabs"
    },
    "copy_to_clipboard": {
      "suggested_key": {
        "default": "Alt+C"
      },
      "description": "Close duplicate tabs"
    }
}
```

### 実際のスクリプトファイル
ここまでが共通的なChrome拡張で必要なJavaScript以外の知識となります。

その他、実際にTypeScriptを使ってChrome拡張を作るにあたって必要なものは先人が既にGithubに公開されているので、そちらを使わせていただきましょう!!!

#### [chibat/chrome-extension-typescript-starter: Chrome Extension TypeScript Starter](https://github.com/chibat/chrome-extension-typescript-starter)

オールインワンで必要なものが一式揃っているのでこちらのレポジトリをダウンロードしたり、forkして作成するのが一番導入が早いかと思います。
私もこちらのレポジトリを参考に、勉強用にChrome拡張を作成しています。
初心者が一番最初に躓くのが最初の下準備なので、ゼロから一式揃えられるくらいの知識を積むまでは先人の知恵をお借りするをオススメします。
(導入で躓いてやる気を無くすのが一番もったいない!)


エディタは好みもあるので、一番慣れているものを使うのが良いのですが、[Visual Studio Code(以下VSCode）](https://azure.microsoft.com/ja-jp/products/visual-studio-code/)ではデフォルトでTypeScriptをサポートしています。
TypeScriptを初めてみようという方にはVSCodeがオススメです！

# 導入

事前に `npm` のインストールが必要になります。
macをお使いの場合は、 Node.js のバージョンマネージャをインストールすることをおすすめします。
私自身は `nodebrew` を使っています。


前述のレポジトリを[ダウンロード](https://github.com/chibat/chrome-extension-typescript-starter/archive/master.zip)します。

VSCodeでこのディレクトリを開き、`View` -> `Terminal` を開き、カレントディレクトリ上で `npm install` を実行したあと、 `npm run watch` と実行しておけば、ソースコードを修正するたびにコンパイルが実行され、最新の状態のJavaScriptファイルが `dist` ディレクトリ上に展開されるようになります。

# おわりに

私自身が本を読むよりも手と頭を使わないと学習できないタチなので、今回は私がTypeScriptに慣れるために使っているChrome拡張とTypeScriptの学習方法と導入についてご紹介させていただきました！