ReactプロジェクトをwebpackからViteの開発環境に置き換えてみる

# はじめに
webpackを使ったシンプルなプロジェクト作り、開発環境をViteに置き換えてみます。
1度手を動かしてやってみたかったのでやってみました。

# webpack環境を作る
webpack環境をViteに移行するにあたり最初にwebpackの環境を作ります。


## 環境
- @babel/core: 7.26.10
- @babel/preset-env: 7.26.9
- @babel/preset-react: 7.26.3
- babel-loader: 10.0.0
- css-loader: 7.1.2
- html-webpack-plugin: 5.6.3
- style-loader: 4.0.0
- webpack: 5.98.0
- webpack-cli: 6.0.1
- webpack-dev-server: 5.2.0
- react: 19.0.0
- react-dom: 19.0.0


## インストール

必要なパッケージをインストールします。

```bash
# Reactパッケージ
npm install react react-dom

# webpack関連パッケージ
npm install webpack webpack-cli webpack-dev-server html-webpack-plugin

# Babel関連パッケージ
npm install @babel/core @babel/preset-env @babel/preset-react babel-loader

# CSSローダー
npm install css-loader style-loader
```

## webpack設定ファイルの作成

プロジェクトのルートにwebpack.config.jsファイルを作成します。

```javascript:webpack.config.js
import path from 'node:path';
import HtmlWebpackPlugin from 'html-webpack-plugin';

/** @type {import('webpack').Configuration} */
const config = {
  mode: 'development',
  entry: './src/index.jsx',
  
  // ビルド出力の設定
  output: {
    filename: '[name].[contenthash].js',
    path: path.resolve(import.meta.dirname, './dist'),
    clean: true,
  },
  
  // 最適化の設定
  optimization: {
    splitChunks: {
      chunks: 'all',
      cacheGroups: {
        vendors: {
          test: /[\\/]node_modules[\\/]/,
          name: 'vendors',
        },
      },
    },
  },
  
  // ファイルの処理ルール
  module: {
    rules: [
      {
        test: /\.jsx?$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: [
              '@babel/preset-env',
              ['@babel/preset-react', { runtime: 'automatic' }]
            ]
          }
        },
      },
      {
        test: /\.css$/,
        use: ['style-loader', 'css-loader'],
      }
    ],
  },
  
  // webpack プラグイン
  plugins: [
    new HtmlWebpackPlugin({
      template: './public/index.html',
    }),
  ],
  resolve: {
    extensions: ['.js', '.jsx'],
  },
  
  // 開発サーバーの設定
  devServer: {
    port: 3000,
    hot: true,
    open: true,
  },
};

export default config;
```


# Reactの実装

## 1. HTMLテンプレート
public/index.htmlファイルを作成します。

```html:index.html
<!DOCTYPE html>
<html lang="ja">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>webpack React App</title>
    </head>
    <body>
        <div id="root"></div>
    </body>
</html>
```

## 2. エントリーポイント

src/index.jsxファイルを作成します。

```jsx:src/index.jsx
import React from 'react';
import { createRoot } from 'react-dom/client';
import App from './App';
import './styles.css';

const container = document.getElementById('root');
const root = createRoot(container);
root.render(<App />);
```

## 3.コンポーネント

src/App.jsxファイルを作成します。

```jsx:App.jsx
import { useState } from 'react';
import Counter from './components/Counter';

function App() {
  const [message, setMessage] = useState('Hello, webpack!');

  return (
    <div className="app">
      <h1>{message}</h1>
      <button onClick={() => setMessage('Hello, React!')}>
        Change Message
      </button>
      <Counter />
    </div>
  );
}

export default App;
```

src/components/Counter.jsxファイルを作成します。

```jsx:Counter.jsx
import { useState } from 'react';

function Counter() {
  const [count, setCount] = useState(0);

  return (
    <div className="counter">
      <h2>Counter: {count}</h2>
      <button onClick={() => setCount(count + 1)}>Increment</button>
      <button onClick={() => setCount(count - 1)}>Decrement</button>
    </div>
  );
}

export default Counter;
```

スタイルも当てたいのでcssを作成しておきます。

<details><summary>styles.css</summary>

src/styles.cssファイルを作成しておきます。

```css:styles.css
body {
  font-family: Arial, sans-serif;
  margin: 0;
  padding: 0;
  background-color: #f5f5f5;
}

.app {
  max-width: 800px;
  margin: 0 auto;
  padding: 20px;
  background-color: white;
  border-radius: 8px;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
  margin-top: 50px;
}

h1 {
  color: #333;
}

button {
  background-color: #0066cc;
  color: white;
  border: none;
  padding: 8px 16px;
  margin-right: 8px;
  border-radius: 4px;
  cursor: pointer;
}

button:hover {
  background-color: #0055aa;
}

.counter {
  margin-top: 20px;
  padding: 16px;
  border: 1px solid #ddd;
  border-radius: 4px;
}
```

</details>


## 4. package.jsonの修正

今回はwebpack.config.jsをES Modules形式で書いてるのでpackage.jsonに"type":"module"の追記と、scriptsセクションに開発サーバを立ち上げるコマンドを記載しておきます。

```json:package.json
"type": "module"
～～
"scripts": {
    "start": "webpack serve"
}
```

## 5. 動作の確認

ここまで出来たら以下のコマンドで開発サーバーを起動します。

```bash
npm start
```

以下のように画面が立ち上がることが確認できました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1247619/d49d67d7-519b-480b-83b7-5d2e084a2dc2.png)

これでwebpackを使用したシンプルなReactプロジェクトの設定が完了しました。
ここまでできたら、続いて開発環境をwebpackからViteに移行していきます。


# Viteの設定

## 環境

- vitejs/plugin-react: 4.3.4
- vite: 6.2.3
- react: 19.0.0
- react-dom: 19.0.0

## 1. Vite関連パッケージのインストール

Viteとそのプラグインをインストールします。

```bash
npm install vite @vitejs/plugin-react
```

webpackとBabel関連、cssのローダーパッケージは、依存関係に残っていても動きますがもし完全にViteに移行する場合は削除しておきます。

```bash
npm uninstall webpack webpack-cli webpack-dev-server html-webpack-plugin @babel/core @babel/preset-env @babel/preset-react babel-loader css-loader style-loader
```

## 2. Vite設定ファイルの作成

プロジェクトのルートにvite.config.jsファイルを作成します。

```javascript:vite.config.js
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';

export default defineConfig({
  plugins: [react()]
});
```

## 3. HTMLファイルの移動・修正

プロジェクトのルートにHTMLファイルを移動します。

```bash
mv public/index.html ./index.html
```

HTMLファイルを更新して、エントリーポイントへの参照を追加します。

```html
<!DOCTYPE html>
<html lang="ja">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Vite React App</title>
    </head>
    <body>
        <div id="root"></div>
        <script type="module" src="/src/index.jsx"></script>
    </body>
</html>
```

## 4. package.jsonの更新

package.jsonのscriptsセクションを更新して、Viteコマンドを使用するようにします。

```json:package.json
"scripts": {
  "dev": "vite",
  "build": "vite build",
  "preview": "vite preview"
}
```

## 動作の確認

以下のコマンドでViteの開発サーバーを起動します。

```bash
npm run dev
```

画面が立ち上がることを確認できました。
webpackでは開発サーバーでホットリロード機能を使うために、webpack-dev-server をインストールしてましたが、Viteではデフォルトでホットリロード機能が利用できて便利です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1247619/50f897fd-f0b1-493a-ba5c-cf810225f260.png)


今回のようにシンプルなプロジェクトであれば、webpackからViteへの移行は簡単だと思いますが、大規模プロジェクトでは使ってるパッケージやその依存関係により移行も難しくなると思います。