webpackからviteへreplaceしてみた

ここ1年ぐらいで、「viteめちゃ早いで」みたいな記事をよく見かけるようになり、どんなもんよ、ということで試したくなりました。

viteの概要についての記事は数あれど、replaceするといった話は少ないように感じたので、本稿ではwebpackからviteへreplaceするために必要な手順について解説していきたいと思います。
viteへreplaceする際の工数見積もりや品質担保の参考になりますと幸いです。

※本稿ではdevserverを起動するまでをゴールとし、production buildについては別途設定が必要となります。



# 現行サービスについて

現行サービスの概要は以下になります。

 - webpack
    - 環境変数は.envで管理
 - React(状態管理はmobx）
 - TypeScript & JavaScript
 - Sass
 

# replace手順

### 1 pluginの追加
pluginとしては以下を`devDependencies`に追加しました。

- vite
- @vitejs/plugin-react
    - vite環境でreactの実行に必用
- @vitejs/plugin-react-refresh
    - vite環境における[React Refresh](https://www.npmjs.com/package/react-refresh)をサポート
- sass
    - vite環境におけるSassをサポート
    - 追加しないでSassを利用しようとするとerrorが発生します。

### 2 vite.config.tsの設定

viteを使用するためのconfigを設定します。
webpackと比較して、コンパクトに記載することができています。

```ts:vite.config.ts
import react from "@vitejs/plugin-react";
import dotenv from "dotenv";
import path from "path";
import { defineConfig } from "vite";

export default () => {
    // 環境変数をdotenvで読み込み、process.envから使用可能にする
    const dotenv_path = path.resolve(".env");
    dotenv.config({ path: `${dotenv_path}` });

    // devserverの設定
    return defineConfig({
        server: {
            port: 8080,

            // 複数サービスと接続するための設定
            proxy: {
                "/change": {
                    target: process.env.SERVER1,
                },
                "/upload": {
                    target: process.env.SERVER2,
                },
            },
        },
        plugins: [
            react({
                babel: {
                    plugins: [
                        // mobxのdecoratorを使用しているため
                        ["@babel/plugin-proposal-decorators", { legacy: true }],

                        // 一部classにおいて、constructor外でプロパティを設定しているため
                        [
                            "@babel/plugin-proposal-class-properties",
                            { loose: true },
                        ],
                    ],
                },
            }),
        ],

        // 本来であればnode_modulesで管理すべきですか、歴史が長いサービスでは
        // コアロジックで使用しているライブラリなどをgit管理しているかもしれません
        // その場合、事前bundleするための設定を記載します
        optimizeDeps: {
            include: ["./src/library/jquery-1.x.xmin.js"],
        },
    });
};

```
### 3 tsconfig.jsonの設定
viteでは環境変数を`import.meta`経由で使用するため、デフォルトでは`esnext`を指定する必要があります。
ただし、[commonjsをサポートするplugin](https://github.com/originjs/vite-plugins/tree/main/packages/vite-plugin-commonjs)などもあるので、適宜利用を検討してみてください。

```json:tsconfig.json
{
    "compilerOptions": {
        "module": "esnext",
        "target": "esnext",
        .
        .
        .
    }
}

```
### 4 envファイルの設定
viteは環境変数を`import.meta.VITE_HOGE`の形式で読み込むことが可能です。
ただし、TypeScriptで`import.meta`を使用するためにはinterfaceとして`ImportMeta`を記載する必要があります。

```txt:env
SERVER1="https://hoge.com"
SERVER2="https://fuga.com"
VITE_HOGE="hoge"
```

```ts:env.d.ts
interface ImportMeta {
    VITE_HOGE: string;
}
```

```ts:example.ts
const hoge = import.meta.VITE_HOGE;

// output "hoge"
console.log(hoge);

```

### 5 拡張子の変更
対象者は少ない気がしますが、Reactコンポーネントを`.js`で定義している方は`.jsx`に変換する必要があります。

### 6 htmlファイルの修正
今まではwebpackのconfigにentryとして記載していた、index.jsxなどをhtmlに直接定義する必要があります。
[公式ドキュメント](https://ja.vitejs.dev/guide/#:~:text=main%20my-project-,index.html%20%E3%81%A8%E3%83%95%E3%82%9A%E3%83%AD%E3%82%B7%E3%82%99%E3%82%A7%E3%82%AF%E3%83%88%E3%83%AB%E3%83%BC%E3%83%88)にも記載されていますが、viteではhtmlもソースコードの一部として利用するためです。


```html:index.html
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <meta charset="utf-8" />
        <title>vite example</title>
    </head>
    <body>
        <script type="module" src="/src/index.jsx"></script>
    </body>
</html>

```


### 7 npm scriptsを定義

vite.config.tsを読み込んでdevserverを起動するためのスクリプトを記載

```json:package.json
{
    "name": "vite-example",
    "version": "1.0.0",
    "scripts": {
        "start": "vite serve --config ./config/vite.config.ts"
    },
    .
    .
    .
}

```


### 最後に

動的importという性質上、画面表示までに微妙なラグがあるなとは思いましたが、
初回起動に関しては、webpackの比ではないです。
尋常じゃない速さでした。
今後も注目していきたいと思います。