Vite + SvelteでChromeの拡張機能を作成する

何番煎じだという感じですが、
Vite + SvelteでChromeの拡張機能を作成する環境を作ったので詰まったところなどをまとめます。
今回はいわゆるnpm init vite
を実行して設定されるパッケージのみを使って環境を作りました。
(SvelteじゃなくてViteの説明がメインなので別のフレームワークでも使えるかも)
ゴールとしては設定ファイルであるmanifest.json
を含めてファイルをビルドし、
出力先を指定することを拡張機能を利用できるようにします。
(+ HMRも利用できるようコマンド設定する)
この設定で作ろうと思ったきっかけなんですが、
拡張機能を作ろうと検索していたところ、
ヘルパーとしてCRXJSが有名なようで、ちょこちょこ色々な記事で名前を見ました。
ですが、こちらは更新がかなり止まっており、
メンテナーがいなければ、アーカイブされちゃうよーとのことなので、
依存する部分少な目でいきたいなと思ったのが理由です。

今回は使いませんが、
調べているうちに、拡張機能を作るに当たって、
役立ちそうなものがあったのでリンクを置いておきます。
(多機能過ぎるので今回は使いませんでした)
- Svelte Typescript Chrome Extension Boilerplate
Svelteを利用するためのボイラープレート
しっかり作りこまれたリポジトリで、あらゆるタイプの拡張機能を作れるようになっている。
https://github.com/NekitCorp/chrome-extension-svelte-typescript-boilerplate - WXT
Chrome拡張開発用のフレームワーク
SvelteやReactなどのUIライブラリとも統合されている。
https://wxt.dev/

Viteの初期設定
まずは任意のフォルダでnpm init vite
を実行し、SvelteとTypescriptを選択します。
実行したらこんな感じになると思います。
| .gitignore
| index.html
| package-lock.json
| package.json
| README.md
| svelte.config.js
| tsconfig.json
| tsconfig.node.json
| vite.config.ts
+---.vscode
| extensions.json
+---public
| vite.svg
\---src
| app.css
| App.svelte
| main.ts
| vite-env.d.ts
+---assets
| svelte.svg
\---lib
Counter.svelte
Chrome拡張機能用ファイルの作成
次はChrome拡張用の設定ファイルを作成します。
※詳しい説明はこの辺りを参照。
今回はポップアップを作るとして設定します。
(拡張機能のアイコンを押すと小さいウィンドウが出るやつです)
manifest.jsonの作成
public
フォルダ内に、manifest.json
を作成します。
ファイルの中身は以下の通りです。
{
"manifest_version": 3,
"name": "SampleExtension",
"description": "Sample extension",
"version": "1.0",
"action": {
"default_popup": "popup.html"
}
}
publicフォルダの扱い
Viteで言うところのpublic
フォルダは静的ファイルの配置場所なので、
npm run build
(vite build
)を実行すると、dist
フォルダにそのままコピーされます。
ですので、拡張機能アイコンを置く場合はここになると思います。
public/icons/sample.png
とかって配置した場合は、manifest.json
で以下のように参照します。
{
"manifest_version": 3,
"name": "SampleExtension",
"description": "Sample extension",
"version": "1.0",
+ "icons": {
+ "16": "icons/sample_16.png",
+ "32": "icons/sample_32.png",
+ "48": "icons/sample_48.png",
+ "128": "icons/sample_128.png"
+ },
"action": {
"default_popup": "popup.html",
+ "default_icon": "icons/sample_48.png"
}
}
popup.htmlの作成
動きとしてポップアップが出るのは定義できたので、ポップアップの中身になるhtmlを作ります。
ポップアップ用のhtmlはpopup.html
という名前でないと認識されない?ようなので、
Svelteのコンポーネントを読み込める状態のhtmlを作って、
ビルド対象として読み取れるようにしたいと思います。
ここでは、デフォルト生成されたindex.html
の名前をpopup.html
にリネームします。
index.html
は/src/main.ts
をscriptタグで読み込んでいますが、
この/src/main.ts
がSvelteのエントリーポイントになっています。
(appというidのついた要素の操作を許可して、DOMをいじれるようにしていますね)
ただ、このままではpopup.html
がビルド対象として認識されないので、
以下のようにvite.config.ts
の設定を変更します。
import { defineConfig } from "vite";
import { svelte } from "@sveltejs/vite-plugin-svelte";
// https://vitejs.dev/config/
export default defineConfig({
plugins: [svelte()],
+ build: {
+ rollupOptions: {
+ input: {
+ popup: "popup.html",
+ },
+ },
+ },
});
デフォルトではindex.html
のみを読み取りますが、
rollupの設定を変更することでinputを変更することができます。
ここで設定することで、scriptタグで指定したtsファイルの依存関係をバンドルしてくれます。
(当初はこの辺り分からずpopup.html
は静的なので、main.tsのみをトランスパイルしていたが、
動的に生成されたCSSファイルがhtmlに紐づかないのでスタイルが適用されなかった)
拡張機能の読み込み
この時点でフォルダ構成はこんな感じになってるかなと思います。
| .gitignore
| package-lock.json
| package.json
| popup.html
| README.md
| svelte.config.js
| tsconfig.json
| tsconfig.node.json
| vite.config.ts
+---.vscode
| extensions.json
+---dist
| | manifest.json
| | popup.html
| | vite.svg
| \---assets
| popup-1531a8fc.js
| popup-9ea02431.css
| svelte-a39f39b7.svg
+---public
| manifest.json
| vite.svg
\---src
| app.css
| App.svelte
| main.ts
| vite-env.d.ts
+---assets
| svelte.svg
\---lib
Counter.svelte
npm run build
(vite build
)を実行すると、
dist
フォルダにビルド結果が出力されます。
Chromeから読み取る際はこのフォルダを指定すれば大丈夫です。
HMRの適用
ViteのHMRを活用したいため、ビルドコマンドの設定を変更します。
デフォルトのビルドコマンドはvite build
ですが、
ファイルの変更を検知して再ビルドするためにvite build --watch
をpackage.jsonに設定します。
(watch
コマンドで設定して、npm run watch
で呼べるようにします)
Viteの開発用サーバーを立ち上げて、それをmanifest.json
で見たり、、とかもできるようですが、
手間がかかりそうなので一旦ここまでで。

拡張機能作っていて気付いたけど、
manifest.jsonを修正した場合はChromeから再読み込みをしないと設定が反映されないですね。
htmlやjsを変更して再ビルドした場合は変更が検知されるけれど、
manifest.jsonの場合は再ビルドしてから再読み込みが必要でした。