【Typescript】Chrome拡張機能をホットリロードで開発したら快適すぎた件
今回初めてChromeの拡張機能を作ってみようと思ったのですが、Vueなど最近のライブラリに慣れてしまったのでホットリロードがないのはとても苦しい…
そこで色々と調べてみた結果、Typescriptで書きwebpackでビルド(ホットリロード)する構成にしました。
構成内容
- Node.js v16.5.0
- Typescript v4.4.2
- webpack v5.52.0
環境構築
各種インストール
1.npmの新規プロジェクトを作成
package.json等が作られます。
mkdir chrome-extension
cd chrome-extension
npm init y
2.webpack、webpackのプラグインをインストール
npm install --save-dev webpack webpack-cli copy-webpack-plugin@5.1.2
webpack本体と、webpackのコマンドラインインターフェースであるwebpack-cli、今回build時にファイルをバンドルせずに単体でコピーするためのcopy-webpack-pluginというプラグインの3つをここでインストールしています。
copy-webpack-pluginは最新バージョンだとメソッドの構文が変わったせいか、自分ではうまく対処できなかったので古いバージョンを使いました。
3.Typescriptの導入
npm install --save-dev typescript ts-loader
Typescript本体と、webpackでTypescriptを処理できるようにするためのts-loaderをインストール
4.Chrome の型定義をインストール
npm install --save-dev @types/chrome
必要なファイルを追加
.
├── node_modules
├── package.json
└── package-lock.json
現在↑のようなファイル構成になっているかと思いますが、↓になるようフォルダ/ファイルを作成してください。
.
├── node_modules
├── public
│ ├── image
│ │ └── icon128.png # Chrome 拡張のアイコン
│ └── manifest.json # Chrome 拡張の設定ファイル
├── src
│ └── content.ts # 実際にChrome上で動作するファイル
├── package.json
├── package-lock.json
├── tsconfig.json # TypeScript の設定
└── webpack.config.js # webpack の設定
content.ts
こちらは実際にChromeで動作させたいことを書くファイルです。
今回はビルドするまでが目的なのでHello Worldを吐くだけにしておきます。
window.alert('Hello World!')
tsconfig.json
{
"compilerOptions": {
"target": "es6",
"module": "commonjs",
"strict": true,
"rootDir": "src",
"esModuleInterop": true,
"typeRoots": [ "node_modules/@types"]
},
"exclude": [
"node_modules"
]
}
webpack.config.js
const path = require("path");
const CopyPlugin = require("copy-webpack-plugin");
module.exports = {
mode: process.env.NODE_ENV || "development",
entry: {
content: path.join(__dirname, "src/content.ts")
},
output: {
path: path.join(__dirname, "dist/js"),
filename: "[name].js",
},
module: {
rules: [
{
test: /\.ts$/,
use: "ts-loader",
exclude: /node_modules/,
},
],
},
resolve: {
extensions: [".ts", ".js"],
},
plugins: [
new CopyPlugin([{ from: ".", to: "../" }], { context: "public" })
],
};
manifest.json
{
"short_name": "short name",
"name": "sample name",
"manifest_version": 2,
"description": "説明記入欄",
"version": "0.0.1",
"icons": { "128": "image/icon128.png" },
"page_action": {
"default_popup": "index.html",
"default_title": "default title"
},
"content_scripts": [
{
"matches": [ "https://www.google.com/*" ],
"js": [ "js/content.js" ]
}
]
}
manifest.jsonの詳しい書き方は今回は省略します。
icon128.pngはアイコンになる画像です。適宜画像を用意してください。
ビルド
以下のコマンドで実際にビルドしてみます。
npx webpack --mode development
すると、distフォルダが作成され、画像、manifest.jsonがコピーされ、tsはjsに変換されているのがわかるかと思います。
.
├── node_modules
├── dist
│ ├── image
│ │ └── icon128.png
│ ├── js
│ │ └── content.js
│ └── manifest.json
├── public
│ ├── image
│ │ └── icon128.png
│ └── manifest.json
├── src
│ └── content.ts
├── package.json
├── package-lock.json
├── tsconfig.json
└── webpack.config.js
ホットリロード
作成したChromeの拡張機能の挙動を確認するには、実際に手元のChromeにビルドしたものを読み込ませて確認するしか手段はありません。
なのでいちいちコードを変更してはビルドして…となると非常に手間です。
webpackには差分を検知してビルドしてくれるホットリロード機能が備わっています。
なのでpackage.jsonに以下をスクリプトとして登録しておきます。
"dev": "webpack --mode development --watch"
するとpackage.jsonはこんな感じ。
{
"name": "chrome-extention-amazon",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"dev": "webpack --mode development --watch"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"@types/chrome": "^0.0.157",
"copy-webpack-plugin": "^5.1.2",
"ts-loader": "^9.2.5",
"typescript": "^4.4.2",
"webpack": "^5.52.0",
"webpack-cli": "^4.8.0"
}
}
次回からは$ npm run dev
で差分を検知して自動でビルドしてくれます。
あとは
・chromeの拡張機能の一覧画面に行き、
・デベロッパーモードをONにする
・『パッケージ化されていない拡張機能を読み込む』でdistフォルダを選択
・ホットリロードされたら、『更新』ボタンを押す

以上です。
動作確認
今回はmanifest.jsonのmatchesにhttps://www.google.com/*と記述したので、googleのサイト上でHello World!と表示されるようになっています。
試しにこちらにアクセスしてアラートが出てきたら成功です。

ホットリロードと言っても、ローカル環境で開発できるわけではないのでchromeのほうで更新ボタンを押さなければいけないのは少し煩わしいですね…
ですが毎度ビルドしなくて良いので作業効率は格段に上がりました。

zawa1205
webフロントエンドエンジニア