okaryo.log

Chrome拡張開発で使っているビルドツールをwebpackからViteに移行した | okaryo.log

Chrome拡張開発で使っているビルドツールをwebpackからViteに移行した

    #Chrome拡張#TabTabTab#Vite#webpack

はじめに

個人開発で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.jsonbackgroundにモジュール設定を追加。また、モジュールは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 devnpm run buildでViteが利用できるようになった。

余談だが、Viteに移行した後、ストアで表示されるパッケージのサイズが376Kib154Kibに削減されるという副次的な効果があった。これは自分がwebpackの最適化をサボっていただけではあるが、簡単な設定でwebpackと同等、もしくはそれ以上の効果があってとても満足している。

おわり

プロジェクトサイズが小さいというのもあるが、Vite自体の設定が簡単なので比較的楽に移行が完了した。

これでいわゆる”✝️モダン✝️”な開発環境に近づくことができた。


関連記事
最新記事
プロモーション

This site uses Google Analytics.