create-react-appで作成したアプリケーションをviteに移行する

[create-react-app](https://create-react-app.dev/) がどうやらメンテされなくなったようで [react-script](https://github.com/facebook/create-react-app/tree/main/packages/react-scripts) が邪魔をして TypeScript を5以降にバージョンアップできなくなった。そのため、create-react-app で作成されたアプリケーションを [Vite](https://vitejs.dev/) に移行する。

> 更新すると以下のようなエラーが出る。

```sh
$ npm update
npm ERR! code ERESOLVE
npm ERR! ERESOLVE could not resolve
npm ERR!
npm ERR! While resolving: react-scripts@5.0.1
npm ERR! Found: typescript@5.3.2
npm ERR! node_modules/typescript
npm ERR!   typescript@"^5.3.2" from the root project
npm ERR!
npm ERR! Could not resolve dependency:
npm ERR! peerOptional typescript@"^3.2.1 || ^4" from react-scripts@5.0.1
npm ERR! node_modules/react-scripts
npm ERR!   react-scripts@"5.0.1" from the root project
npm ERR!
npm ERR! Conflicting peer dependency: typescript@4.9.5
npm ERR! node_modules/typescript
npm ERR!   peerOptional typescript@"^3.2.1 || ^4" from react-scripts@5.0.1
npm ERR!   node_modules/react-scripts
npm ERR!     react-scripts@"5.0.1" from the root project
```

Vite はフランス語で"quick"の意味だそうで日本的発音は ヴィート らしい。（実際の発音を聞くと ルフィーツ って聞こえる。）Vue.js を開発した人が開発したらしくとにかく早いらしい。詳しくは[こちら](https://vitejs.dev/guide/why.html)。

こちらのテンプレートで作成したのがベース。

```sh
npx create-react-app my-app --template typescript
```

まずは `Vite` をインストールする。

```sh
npm install --save-dev vite @vitejs/plugin-react
```

react-scripts をアンインストールする。

```sh
npm uninstall react-scripts
```

typescript をインストールする。

```sh
npm install typescript@5.3.2
```

更新した package.json は以下の通り。npm script を vite に書き換えておく。

```diff:package.json
  "dependencies": {
-    "react-scripts": "5.0.1",
-    "typescript": "^4.9.5",
+    "typescript": "^5.3.2",
   },
   "scripts": {
-    "start": "react-scripts start",
-    "build": "react-scripts build",
+    "start": "vite",
+    "build": "tsc && vite build",
+    "preview": "vite preview",
   },
  "devDependencies": {
+    "@vitejs/plugin-react": "^4.2.0",
+    "vite": "^5.0.4"
   }
 }
 ```

これだけだとローカルで起動やビルドが通らないのでファイルも修正する。

プロジェクトのルートに vite.config.ts を作成する。ビルド後のディレクトリ名を react に合わせて 'build' としておく。（デフォルトだと dist）

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

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [react()],
  build: {
    outDir: 'build',
  },
});
```

public/index.html をプロジェクトのルートに移動して修正する。%PUBLIC_URL%は不要なので削除する。

```diff:index.html
 <html lang="en">
   <head>
-    <link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
+    <link rel="icon" href="/favicon.ico" />
-    <link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
+    <link rel="apple-touch-icon" href="/logo192.png" />
-    <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
+    <link rel="manifest" href="/manifest.json" />
   <body>
     <div id="root"></div>
+    <script type="module" src="/src/index.tsx"></script>
```

環境変数が create-react-app の場合は`REACT_APP`始まりだったけど vite の場合は`VITE_`始まりに変わる。詳しくは[こちら](https://vitejs.dev/guide/env-and-mode.html)。

```diff:src/react-app-env.d.ts
-/// <reference types="react-scripts" />
+/// <reference types="vite/client" />
```

ここまでできればビルドしてプレビューしてみる。preview はビルド後のファイルを参照して表示を確認できるので本番に近い状態の動作確認ができる。

```sh
npm run build
npm run preview
```