Chrome拡張開発で使っているビルドツールをwebpackからViteに移行した
はじめに
個人開発でTabTabTabというタブ管理用のChrome拡張を開発している。
開発にはReactとTypeScriptを利用しており、ビルドツールにはwebpackをずっと利用していた。
特に巨大なプロジェクトでもないし、ビルド時間や複雑な設定ファイルに困っていたわけではないが、時代はViteなのでTabTabTabでもいつか使ってみたいとずっと思っていた。
最近移行が完了したので内容をまとめておく。
webpackの設定ファイル
まずは以前まで使っていたwebpackの設定ファイルを紹介しておく。
設定ファイルは3つあってそれぞれ共通・開発用・本番用となっており、webpack-merge
を使って合体していた。
// webpack.common.js
const path = require("path");
module.exports = {
entry: {
popup: path.join(__dirname, "src/view/features/popup/index.tsx"),
options: path.join(__dirname, "src/view/features/options/index.tsx"),
background: path.join(__dirname, "src/background/index.ts"),
},
output: {
path: path.join(__dirname, "dist/js"),
filename: "[name].js"
},
module: {
rules: [
{
exclude: /node_modules/,
test: /\.tsx?/,
use: "ts-loader"
},
]
},
resolve: {
extensions: [".ts", ".tsx", ".js"]
}
};
// webpack.dev.js
const { merge } = require("webpack-merge");
const common = require("./webpack.common.js");
module.exports = merge(common, {
mode: "development",
devtool: "inline-source-map"
});
// webpack.prod.js
const { merge } = require("webpack-merge");
const common = require("./webpack.common.js");
module.exports = merge(common, {
mode: "production"
});
package.json
のスクリプトは以下。npm run watch
でホットリロードとなる。
{
"scripts": {
"build": "webpack --config webpack.prod.js",
"dev": "webpack --config webpack.dev.js",
"watch": "webpack -w --config webpack.dev.js"
}
}
Viteの導入
まずは必要なパッケージをインストール。Reactを利用しているので@vitejs/plugin-react
というプラグインを利用している。Fast RefreshやJSXトランスフォームの対応などをやってくれる。
npm i -D vite @vitejs/plugin-react
そして今回導入したViteの設定ファイルが以下。基本的にwebpackの設定内容をほぼ踏襲している。
// vite.config.ts
import { defineConfig } from "vite";
import path from "path";
import react from "@vitejs/plugin-react";
export default defineConfig(({ mode }) => {
const isDev = mode === "development";
const isProduction = !isDev;
return {
plugins: [react()],
build: {
outDir: "dist/js",
sourcemap: isDev,
minify: isProduction,
reportCompressedSize: isProduction,
rollupOptions: {
input: {
popup: path.resolve(__dirname, "src/view/features/popup/index.tsx"),
options: path.resolve(
__dirname,
"src/view/features/options/index.tsx",
),
background: path.resolve(__dirname, "src/background/index.ts"),
},
output: {
entryFileNames: "[name].js",
chunkFileNames: isDev
? "assets/[name].js"
: "assets/[name].[hash].js",
},
},
},
};
});
Viteを導入するにあたって調べてみると、Chrome拡張でViteを利用するのに@crxjs/vite-plugin
を導入している記事が多かった。拡張の設定を記述するmanifest.json
をTSファイルで書けたりと便利な面がありそうだったが、自分は特に不自由していないので入れなかった。
package.json
のスクリプトは以下。開発時は基本的にホットリロードしか使わないのでnpm run dev
でホットリロードが効くようにした。
{
"scripts": {
"dev": "vite build --watch --mode development",
"build": "vite build"
}
}
その他必要だった対応
今回のViteではビルド時にチャンクファイルを作成するようにしたのでモジュール対応がいくつか必要となった。
まずはmanifest.json
のbackground
にモジュール設定を追加。また、モジュールはjs/assets
に配置されてリソースとして参照されるので、Web Accessible Resources
対応が必要となった。
{
"background" : {
"service_worker" : "js/background.js",
"type": "module"
},
"web_accessible_resources": [
{
"resources": ["js/assets/*"],
"matches": ["*://*/*"]
}
]
}
また、今までJSファイルを読み込んでいた箇所でもモジュール対応が必要。
// popup.html
<script type="module" src="js/popup.js"></script>
// options.html
<script type="module" src="js/options.js"></script>
以上でViteへの移行が完了し、npm run dev
やnpm run build
でViteが利用できるようになった。
余談だが、Viteに移行した後、ストアで表示されるパッケージのサイズが376Kib
→154Kib
に削減されるという副次的な効果があった。これは自分がwebpackの最適化をサボっていただけではあるが、簡単な設定でwebpackと同等、もしくはそれ以上の効果があってとても満足している。
おわり
プロジェクトサイズが小さいというのもあるが、Vite自体の設定が簡単なので比較的楽に移行が完了した。
これでいわゆる”✝️モダン✝️”な開発環境に近づくことができた。