【拡張機能】Viteを使ってReactで複数のページを作る(ポップアップとオプション用)
ReactはSPAを構築するのに便利ですが拡張機能を作るときには不便な点があります。ポップアップとオプションページは独立しているので通常どちらか1つのページでしかReactを使ったフロントエンド開発が行えません。そこでViteを使ってReactで2つの独立したページを作って(MPA)、ポップアップとオプションページの両方でReactを使えるようにしましょう。
以下のツールを使って拡張機能を作っていきます
- Vite
- TypeScript
- React
- CRXJS
1.Viteで初期化
npm init vite@latest
このとき初期設定をするための質問をされますので次のようにしてください。
- Project Name: sample-multi (これは任意)
- Select a framework: React
- Select a varieant: TypeScript
2.パッケージをインストール
初期設定で用意されているパッケージをインストールする。
cd sample-multi
npm install
3.crxjs をインストール
npm i -D @crxjs/vite-plugin@beta
@crxjs/vite-plugin@betaViteユーザーのChrome拡張用プラグイン。Vite3もVite4も対応がまだなので公式サイトでもベータを使うようにとのこと。
vite.config.js
ファイルを書き換える
4.import { defineConfig } from "vite";
import { crx } from "@crxjs/vite-plugin";
import manifest from "./manifest.json";
export default defineConfig({
plugins: [crx({ manifest })],
build: {
rollupOptions: {
input: {
popup: 'src/popup/popup.html',
options: 'src/options/options.html'
}
}
},
// WebSocket connection to 'ws://localhost/' failed: というエラーの対策
// https://github.com/crxjs/chrome-extension-tools/issues/746#issuecomment-1647484887
server: {
port: 5174,
strictPort: true,
hmr: {
port: 5174,
},
},
});
MPA に対応するポイント
ReactをMPAに対応するためのポイントはbuild
オプションで設定されている項目です。このオプションの中のinput
キーの中でエントリーポイントとなる複数のhtmlファイルを指定できます。今回はポップアップとオプションページの2つのページを作りたいので次の2つを設定しています。
// (一部抜粋)
build: {
rollupOptions: {
input: {
popup: 'src/popup/popup.html',
options: 'src/options/options.html'
}
}
},
manifest.json
を作成する
5.{
"manifest_version": 3,
"name": "MPA sample",
"version": "1.0.0",
"action": { "default_popup": "src/popup/popup.html" },
"options_page": "src/options/options.html"
}
6.ポップアップページ関連のファイルを作成する。
src
直下にpopup
ディレクトリを作成しポップアップに関連するファイルを作成します。Reactのエントリーポイントとなるhtmlファイルと、ReactでDOMを作成するためのtsxファイルの2つです。通常のReact開発と比較するとsrc/popup/popup.html
はindex.html
に対応し、src/popup/Popup.tsx
はApp.tsx
とmain.tsx
に対応しています。
index.html
に対応するsrc/popup/popup.html
はvite.config.ts
で設定しているパスに対応しています。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Popup</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/popup/Popup.tsx"></script>
</body>
</html>
import { createRoot } from "react-dom/client";
function Popup() {
return (
<div>
<h1>Popup Page</h1>
</div>
);
}
const rootElement = document.getElementById("root") as HTMLElement;
const root = createRoot(rootElement);
root.render(<Popup />);
7.オプションページ関連のファイルを作成する
ポップアップと同様にsrc
直下にoptions
ディレクトリを作成しオプションページに関連するファイルを作成します。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Option</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/options/Options.tsx"></script>
</body>
</html>
import { createRoot } from "react-dom/client";
function Options() {
return (
<div>
<h1>Options Page</h1>
</div>
);
}
const rootElement = document.getElementById("root") as HTMLElement;
const root = createRoot(rootElement);
root.render(<Options />);
8.実行
npm run dev
このコマンドを実行すると dist
というフォルダが作成されている。
9.拡張機能を読み込む
- chrome://extensions/ に移動
- デベロッパーモードがONになっていることを確認
- 「パッケージ化されていない拡張機能を読み込む」をクリック
- 作成したディレクトリに新しくできた
dist
ディレクトリを選択
10.ピン留めしておく
- パズルのピースのアイコンをクリック
- 開発している拡張機能名のピンのアイコンをON
開発中は何度もクリックするので常に表示されるようにしておく。
11.起動できたか確認
ここまでの手順がうまくいくとポップアップとオプションページのそれぞれに次のようなページが表示されます。
ポップアップを開いたとき
オプションページを開いたとき
12.不要なファイルを削除する
デフォルトで作成される不要なファイルを削除します。
index.html
-
public
ディレクトリ -
src/assets
ディレクトリ src/App.css
src/App.tsx
src/index.css
src/main.tsx
@types/chrome
拡張機能開発に必要なAPIのオートコンプリートや型情報が入ったパッケージ。必須。
npm install --save @types/chrome
Discussion