Chrome拡張機能をtypeScript
+ webpack
+ create react app
で開発していますが、ビルドが遅いので、開発でストレスになっていた。
一方、vite
がビルド速度が早いと巷で話題になっているので、まずは土台を作成し、本当に早いのか検証してみました。
使用環境
会社で使用しているMacなので、かなりハイエンドのものを使用していますが、ここまでのスペックじゃなくても問題なく利用はできると思います。
- MacBook Pro (16-inch, 2019)
- OS: MacOSX 10.15.7
- CPU: 2.4 GHz 8コアIntel Core i9
- メモリ:64 GB 2667 MHz DDR4
- node v12.13.1
ベースで使用したもの
react-ts
というテンプレートから作成しています。
yarn create @vitejs/app --template react-ts .
やったことまとめ
作成したものは、以下においてありますが、やった内容をまとめておきます。
package.json
の変更
以下の変更を行っています
-
yarn build
時に、tsc
に--noEmit
オプションを追加(型検査のみで十分なので) - パッケージを追加
- chrome関係のものをtypescriptで利用するのに必要
@types/chrome
- ビルドで必要
rollup-plugin-copy
@types/node
- chrome関係のものをtypescriptで利用するのに必要
{
"name": "vite_for_chrome_extension",
"version": "0.0.0",
"scripts": {
"dev": "vite",
"build": "vite build",
"serve": "vite preview"
},
"dependencies": {
"react": "^17.0.0",
"react-dom": "^17.0.0"
},
"devDependencies": {
"rollup-plugin-copy": "3.4.0",
"@types/node": "16.4.0",
"@types/chrome": "0.0.148",
"@types/react": "^17.0.0",
"@types/react-dom": "^17.0.0",
"@vitejs/plugin-react-refresh": "^1.3.1",
"typescript": "^4.3.2",
"vite": "^2.4.3"
}
}
vite.config.ts
を変更
主に、やっていることは以下の通り
-
main.js
やbackgroundスクリプトであるbackground.js
をビルドし、dist
直下へ出力 -
public
ファイルをdist/public
へコピー -
manifest.json
をdist
へコピー -
index.html
などchrome拡張機能で利用するhtml
ファイルをdist
へコピー
import { defineConfig } from 'vite'
import reactRefresh from '@vitejs/plugin-react-refresh'
import copy from 'rollup-plugin-copy'
const { resolve } = require('path')
// https://vitejs.dev/config/
export default defineConfig({
build: {
// src上にあるts, tsxファイルを一つのjsにまとめて、dist配下へ配置
// ポップアップスクリプト本体であるmain.jsと、バックアップスクリプトbackground.jsのビルド設定を含めている
// コンテンツスクリプトは含めていないが、必要であればここに追加していけばよい
rollupOptions: {
input: {
main: resolve(__dirname, 'src/main/main.tsx'),
background: resolve(__dirname, 'src/background/background.ts'),
},
output: {
entryFileNames: '[name].js',
},
},
},
plugins: [
reactRefresh(),
copy({
verbose: true,
hook: 'writeBundle',
targets: [
// publicファイル(アイコンなど) を dist/public へコピー
{
src: 'public/*',
dest: 'dist/public'
},
// manifest.json を distへコピー
{
src: 'manifest.json',
dest: 'dist',
},
// index.htmlなどchrome extensionで使用するhtmlファイルをdistへコピー
{
src: '*.html',
dest: 'dist'
}
],
}),
]
})
src
配下にあるコンポーネントファイルをsrc/main
へ移動
vite-env.d.ts
を除くすべてのファイルをsrc/main
へ移動させた。コンポーネント関係なので、分離してわかりやすくしたかっただけに過ぎません。
background.ts
を作成
background scriptを作成しておきます。とりあえず土台を作成したかったので、何もいれていません。
export {}
public
フォルダを作成
ここにはとりあえず、拡張機能で利用するファビコンやロゴなどを入れています
index.html
を作成
拡張機能アイコンを押したときに、呼び出すindex.html
をルート直下で作成しています。
ここでmain.js
を呼び出すようにしています。
なお、main.js
のパスはビルド時にルート直下で作成されることを想定しているので、以下のようにしています。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="favicon.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite App</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="main.js"></script>
</body>
</html>
manifest.json
を作成
chrome 拡張機能で必須なファイル manifest.json
を作成しておきます。ロゴやバックグラウンドスクリプトbackground.js
、ポップアップで表示させるファイルindex.html
を指定しています。
コンテンツスクリプトは今回含まれていませんが、vite.config.js
でビルドできるようにすればすぐに対応できるようにしています。
{
"manifest_version": 3,
"name": "vite_for_chrome_extension",
"version": "0.0.0.0",
"action": {
"name": "test",
"default_popup":"index.html"
},
"web_accessible_resources" : [{
"resources": [
"index.html", "main.js"
],
"matches": ["http://*/*", "https://*/*", "*://*/*"],
"extension_ids": []
}],
"icons": {
"32": "public/logo192.png",
"64": "public/logo192.png",
"128": "public/logo192.png",
"512": "public/logo192.png"
},
"background" : {
"service_worker" : "./background.js"
},
"content_scripts" : [],
"permissions": [
"tabs",
"webNavigation",
"clipboardWrite",
"clipboardRead",
"storage",
"unlimitedStorage",
"alarms",
"scripting"
],
"host_permissions" : [
"http://*/*",
"https://*/*",
"*://*/*"
]
}
ここまで作成すれば、あとは、yarn build
で拡張機能がビルドできるようになります。
結局早くビルドできるのか?
従来のものと比較して、本当に早くビルドできるのか試してみました。
従来のプロジェクトについては、比較のためにこちらを拝借しました
実際にビルドしてみてかかった時間は以下のとおりです。
- vite: 平均 6.46s (6.81s, 6.37s, 6.21s)
- create-react-app: 平均 5.32s (7.22s, 4.35s, 4.38s)
なんと、vite
のほうが遅いという残念な結果に。。。
なぜ遅いのか調べてみたところ、vite build
の前にtsc
を実行していてこれがビルド時間に足かせになっているようです(実際これを省略してみたところ、平均 2.56s (2.82s, 2.46s, 2.40s)で済み、問題なくビルドできているようです)。
ではなぜtsc
をいれているのかというと、公式マニュアルによると、vite
もといビルドに使っているesbuild
では、あくまでトランスパイルしか行わず、型チェックは行っていないからだそうです。なので、型チェックはtsc
でカバーしているようです。
一方、拡張機能では毎回ビルドすることになるので、当然型チェックは必要です。なので、tsc
は外せられないと考えています。
規模が大きくなるとどうなるかも検証
何も入れていない状態だと、あまり意味がないのかなと思い、規模が大きくなったら本領が発揮されるという話もあるので、検証してみました。
たとえば、React Material UI ( https://material-ui.com/ ) という比較的重いモジュールを含めてみることにしました。バージョンは4.12.2
とします。
その結果がこちらです。
- vite: 平均 10.64s (10.66s, 10.53s, 10.74s)
- vite(tscを除外): 平均 4.46s (4.60s, 4.36s, 4.43s)
- create-react-app: 平均 6.82s (6.77s, 6.87s, 6.81s)
これでもvite
のほうが遅い結果に。。。tsc
を除外したら早いので、ここでもtsc
が足かせになっているようでした。
他にモジュールをいれてみたら結果は変わるかもしれませんが、キリがなさそうなので、ここで打ち切ることにしました。
まとめ
vite
で土台を作ってみたら早くなるのかなと検証していましたが、従来のものと比較して早くビルドされるわけではありませんでした
tsc
がビルド時間の足かせになっていることはわかったものの、型チェックは必要なので外せません。なので、chrome拡張機能で採用するにはまだまだ課題がある印象でした。
今後改善してもっと早くなることがわかれば、またトライしてみたいです。