Closed MofuMofu2 closed 8 months ago
もちろんです。Create React App(CRA)のプロジェクトをViteに移行するための手順を日本語で説明いたします。
新しいViteプロジェクトの初期化:
npm init vite@latest
コマンドを使用して、別のディレクトリに新しいViteプロジェクトを作成します。ソースコードのコピー:
src
および public
フォルダ内にある)ソースファイルを新しいViteプロジェクトにコピーします。依存関係のインストール:
package.json
の依存関係とViteによって作成された新しいものを比較し、プロジェクトに必要な追加の依存関係をインストールします。Viteの設定:
vite.config.js
ファイルで行います。例えば、エイリアスの設定やビルドプロセスの構成が必要になる場合があります。スクリプトの更新:
package.json
のスクリプトをViteのコマンドを使用するように更新します。例えば、開発サーバー用に react-scripts start
を vite
に置き換えます。プロジェクトのテスト:
本番バージョンのビルドとテスト:
環境変数の移行(ある場合):
.env
ファイル)を使用している場合、それらがViteプロジェクトで正しく設定されていることを確認します。オプション: CRA固有の機能からの移行:
react-scripts
の特定の設定など)を使用していた場合、Viteでの同等の解決策を見つけるか、コードをリファクタリングする必要があります。バージョン管理の更新:
これは一般的なガイドラインであり、プロジェクトの詳細によって具体的な手順は異なる場合があります。移行プロセス中に特定の問題やエラーに遭遇した場合は、Viteのドキュメントを参照するか、その特定の問題について助けを求める必要があるかもしれません。
それは微妙そうかもしれないな…。
Vite は Node.js 18+、20+ のバージョンが必要です。
なるほど 🤔
react-ts
テンプレートで作るIEはサポートしない。
お気づきかもしれませんが、Vite プロジェクトでは index.html は public 内に隠れているのではなく、最も目立つ場所にあります。これは意図的なものです。開発中、Vite はサーバーで、index.html はアプリケーションのエントリーポイントです。
https://ja.vitejs.dev/guide/cli.html#vite-preview
プロダクションビルドを開発環境でプレビューできる
```typescript mofumofu at mofunoMacBook-Air in ~/git/react-sandbox (main) $ git checkout -b feature/93-change-vite Switched to a new branch 'feature/93-change-vite' mofumofu at mofunoMacBook-Air in ~/git/react-sandbox (feature/93-change-vite) $ npm install vite @vitejs/plugin-react added 12 packages, changed 34 packages, and audited 1986 packages in 18s 307 packages are looking for funding run `npm fund` for details 16 vulnerabilities (7 moderate, 8 high, 1 critical) To address issues that do not require attention, run: npm audit fix To address all issues (including breaking changes), run: npm audit fix --force Run `npm audit` for details. mofumofu at mofunoMacBook-Air in ~/git/react-sandbox (feature/93-change-vite●) $ git add . mofumofu at mofunoMacBook-Air in ~/git/react-sandbox (feature/93-change-vite●) $ git commit ✔ Preparing lint-staged... ✔ Running tasks for staged files... ✔ Applying modifications from tasks... ✔ Cleaning up temporary files... [feature/93-change-vite cfd1611] feature: #93 Viteのインストール 2 files changed, 1381 insertions(+), 330 deletions(-) mofumofu at mofunoMacBook-Air in ~/git/react-sandbox (feature/93-change-vite) $ git add . g% mofumofu at mofunoMacBook-Air in ~/git/react-sandbox (feature/93-change-vite●) $ git commit ✔ Preparing lint-staged... ✔ Running tasks for staged files... ✔ Applying modifications from tasks... ✔ Cleaning up temporary files... [feature/93-change-vite 58aa1db] feature: #93 スターターコマンドを変更 1 file changed, 2 insertions(+), 2 deletions(-) mofumofu at mofunoMacBook-Air in ~/git/react-sandbox (feature/93-change-vite) $ git push fatal: The current branch feature/93-change-vite has no upstream branch. To push the current branch and set the remote as upstream, use git push --set-upstream origin feature/93-change-vite To have this happen automatically for branches without a tracking upstream, see 'push.autoSetupRemote' in 'git help config'. mofumofu at mofunoMacBook-Air in ~/git/react-sandbox (feature/93-change-vite) $ git push --set-upstream origin feature/93-change-vite Enumerating objects: 10, done. Counting objects: 100% (10/10), done. Delta compression using up to 4 threads Compressing objects: 100% (7/7), done. Writing objects: 100% (7/7), 12.05 KiB | 456.00 KiB/s, done. Total 7 (delta 5), reused 0 (delta 0), pack-reused 0 remote: Resolving deltas: 100% (5/5), completed with 3 local objects. remote: remote: Create a pull request for 'feature/93-change-vite' on GitHub by visiting: remote: https://github.com/MofuMofu2/react-sandbox/pull/new/feature/93-change-vite remote: To https://github.com/MofuMofu2/react-sandbox.git * [new branch] feature/93-change-vite -> feature/93-change-vite branch 'feature/93-change-vite' set up to track 'origin/feature/93-change-vite'. mofumofu at mofunoMacBook-Air in ~/git/react-sandbox (feature/93-change-vite) $ npm run dev > reactjs-sandbox@1.0.0 dev > vite VITE v5.0.10 ready in 1205 ms ➜ Local: http://localhost:5173/ ➜ Network: use --host to expose ➜ press h + enter to show help ```
npm run ejectを実行すると、CRAが今何をしているか出力した上で依存関係を削除できる。 不可逆なので注意が必要。
切る前にこんな感じで警告が出る。CSS Modulesもサポートしているとのこと。 ということは代替しないといけない?
mofumofu at mofunoMacBook-Air in ~/git/react-sandbox (feature/93-change-vite)
$ npm run eject
> reactjs-sandbox@1.0.0 eject
> react-scripts eject
NOTE: Create React App 2+ supports TypeScript, Sass, CSS Modules and more without ejecting: https://reactjs.org/blog/2018/10/01/create-react-app-v2.html
? Are you sure you want to eject? This action is permanent. › (y/N)
$ npm run eject
> reactjs-sandbox@1.0.0 eject
> react-scripts eject
NOTE: Create React App 2+ supports TypeScript, Sass, CSS Modules and more without ejecting: https://reactjs.org/blog/2018/10/01/create-react-app-v2.html
✔ Are you sure you want to eject? This action is permanent. … yes
Ejecting...
`scripts` already exists in your app folder. We cannot continue as you would lose all the changes in that file or directory. Please move or delete it (maybe make a copy for backup) and run this command again.
scripts
が存在するとダメみたいなのでバックアップをとって取り除く。
scriptsディレクトリを消した後再実行すると次のようになった。
```typescript $ npm run eject > reactjs-sandbox@1.0.0 eject > react-scripts eject NOTE: Create React App 2+ supports TypeScript, Sass, CSS Modules and more without ejecting: https://reactjs.org/blog/2018/10/01/create-react-app-v2.html ✔ Are you sure you want to eject? This action is permanent. … yes Ejecting... Copying files into /Users/mofumofu/git/react-sandbox Adding /config/env.js to the project Adding /config/getHttpsConfig.js to the project Adding /config/modules.js to the project Adding /config/paths.js to the project Adding /config/webpack.config.js to the project Adding /config/webpackDevServer.config.js to the project Adding /config/jest/babelTransform.js to the project Adding /config/jest/cssTransform.js to the project Adding /config/jest/fileTransform.js to the project Adding /scripts/build.js to the project Adding /scripts/start.js to the project Adding /scripts/test.js to the project Adding /config/webpack/persistentCache/createEnvironmentHash.js to the project Updating the dependencies Removing react-scripts from dependencies Adding @babel/core to dependencies Adding @pmmmwh/react-refresh-webpack-plugin to dependencies Adding @svgr/webpack to dependencies Adding babel-jest to dependencies Adding babel-loader to dependencies Adding babel-plugin-named-asset-import to dependencies Adding babel-preset-react-app to dependencies Adding bfj to dependencies Adding browserslist to dependencies Adding camelcase to dependencies Adding case-sensitive-paths-webpack-plugin to dependencies Adding css-loader to dependencies Adding css-minimizer-webpack-plugin to dependencies Adding dotenv to dependencies Adding dotenv-expand to dependencies Adding eslint to dependencies Adding eslint-config-react-app to dependencies Adding eslint-webpack-plugin to dependencies Adding file-loader to dependencies Adding fs-extra to dependencies Adding html-webpack-plugin to dependencies Adding identity-obj-proxy to dependencies Adding jest to dependencies Adding jest-resolve to dependencies Adding jest-watch-typeahead to dependencies Adding mini-css-extract-plugin to dependencies Adding postcss to dependencies Adding postcss-flexbugs-fixes to dependencies Adding postcss-loader to dependencies Adding postcss-normalize to dependencies Adding postcss-preset-env to dependencies Adding prompts to dependencies Adding react-app-polyfill to dependencies Adding react-dev-utils to dependencies Adding react-refresh to dependencies Adding resolve to dependencies Adding resolve-url-loader to dependencies Adding sass-loader to dependencies Adding semver to dependencies Adding source-map-loader to dependencies Adding style-loader to dependencies Adding tailwindcss to dependencies Adding terser-webpack-plugin to dependencies Adding webpack to dependencies Adding webpack-dev-server to dependencies Adding webpack-manifest-plugin to dependencies Adding workbox-webpack-plugin to dependencies Updating the scripts Replacing "react-scripts test" with "node scripts/test.js" Configuring package.json Adding Jest configuration Adding Babel preset Adding ESLint configuration Running npm install... > reactjs-sandbox@1.0.0 prepare > husky install husky - Git hooks installed added 36 packages, removed 217 packages, changed 37 packages, and audited 1758 packages in 18s 308 packages are looking for funding run `npm fund` for details 14 vulnerabilities (6 moderate, 7 high, 1 critical) To address issues that do not require attention, run: npm audit fix To address all issues (including breaking changes), run: npm audit fix --force Run `npm audit` for details. Ejected successfully! Staged ejected files for commit. Please consider sharing why you ejected in this survey: http://goo.gl/forms/Bi6CZjk1EqsdelXk1 ```
``` mofumofu at mofunoMacBook-Air in ~/git/react-sandbox (feature/93-change-vite●) $ git commit ✔ Preparing lint-staged... ❯ Running tasks for staged files... ❯ .lintstagedrc.js — 16 files ❯ *.{ts,tsx} — 1 file ✔ npx eslint --fix --rule 'import/order: 2' ✔ npx prettier --write src/react-app-env.d.ts ✖ npx eslint src/react-app-env.d.ts [FAILED] ✔ *.json — 2 files ↓ Skipped because of errors from tasks. [SKIPPED] ✔ Reverting to original state because of errors... ✔ Cleaning up temporary files... ✖ npx eslint src/react-app-env.d.ts: /Users/mofumofu/git/react-sandbox/src/react-app-env.d.ts 1:1 error Do not use a triple slash reference for node, use `import` style instead @typescript-eslint/triple-slash-reference 2:1 error Do not use a triple slash reference for react, use `import` style instead @typescript-eslint/triple-slash-reference 3:1 error Do not use a triple slash reference for react-dom, use `import` style instead @typescript-eslint/triple-slash-reference 48:3 error All imports in the declaration are only used as types. Use `import type` @typescript-eslint/consistent-type-imports 59:18 error A record is preferred over an index signature @typescript-eslint/consistent-indexed-object-style 64:18 error A record is preferred over an index signature @typescript-eslint/consistent-indexed-object-style 69:18 error A record is preferred over an index signature @typescript-eslint/consistent-indexed-object-style ✖ 7 problems (7 errors, 0 warnings) 4 errors and 0 warnings potentially fixable with the `--fix` option. husky - pre-commit hook exited with code 1 (error) ```
この時点で複数のコンフィグができているため1つに絞る必要がある。
$ npm run test
> reactjs-sandbox@1.0.0 test
> node scripts/test.js --watchAll=false
● Multiple configurations found:
* /Users/mofumofu/git/react-sandbox/jest.config.js
* `jest` key in /Users/mofumofu/git/react-sandbox/package.json
Implicit config resolution does not allow multiple configuration files.
Either remove unused config files or select one explicitly with `--config`.
Configuration Documentation:
https://jestjs.io/docs/configuration.html
● Validation Error:
Module ts-jest in the transform option was not found.
<rootDir> is: /Users/mofumofu/git/react-sandbox
Configuration Documentation:
https://jestjs.io/docs/configuration
package.jsonにJestの設定が書かれているため1つにまとめる。jest.conifg.jsとpackage.jsonはファイル形式が異なるためセミコロンを取ったりするのがめんどくさい。GitHub Copilot Chatとかでできないか試してみる。
// コンフィグファイルを開いた状態で次のようにする
@workspace jest.config.jsとpackage.jsonのjestの設定をマージしたいです。マージ結果はjest.oonfig.jsに書き込めるようにしたいです。
[jest.config.js]()と[package.json]()のJest設定をマージするには、Node.jsのrequireと[fs]()モジュールを使用します。以下にその手順を示します:
[package.json]()からJest設定を読み込む [jest.config.js]()から現在の設定を読み込む 両方の設定をマージする マージした設定を[jest.config.js]()に書き込む 以下にそのスクリプトを示します:
const fs = require('fs');
const packageJson = require('./package.json');
const jestConfig = require('./jest.config.js');
// package.jsonからJest設定を取得
const packageJestConfig = packageJson.jest;
// 両方の設定をマージ
const mergedConfig = { ...jestConfig, ...packageJestConfig };
// マージした設定をjest.config.jsに書き込む
fs.writeFileSync('./jest.config.js', `module.exports = ${JSON.stringify(mergedConfig, null, 2)}`);
このスクリプトは、[jest.config.js]()と同じディレクトリで実行する必要があります。また、このスクリプトは[jest.config.js]()と[package.json]()の両方に存在する同じ設定を上書きします。上書きの挙動を変更するには、マージのロジックを調整する必要があります。
ということなので、スクリプトをコミットして実行してみる。
実行コマンド
node merge-script.js
いい感じにmergeできた。Node.jsのファイルストリームAPIでファイルを読み取ってJSON.stringifyでMergeする。
```typescript
$ npm run test
> reactjs-sandbox@1.0.0 test
> node scripts/test.js --watchAll=false
PASS src/store/todoStore.test.ts
● Console
console.error
Warning: ReactDOM.render is no longer supported in React 18. Use createRoot instead. Until you switch to the new API, your app will behave as if it's running React 17. Learn more: https://reactjs.org/link/switch-to-createroot
8 | describe("グローバルステートの初期値に関するテスト", () => {
9 | it("ステートの初期値が意図通りにセットされていること", () => {
> 10 | const { result } = renderHook(() => useRecoilValue(todoAtom), {
| ^
11 | wrapper: RecoilRoot,
12 | });
13 | expect(result.current).toEqual([
at console.error (node_modules/@testing-library/react-hooks/lib/core/console.js:19:7)
at printWarning (node_modules/react-dom/cjs/react-dom.development.js:86:30)
at error (node_modules/react-dom/cjs/react-dom.development.js:60:7)
at Object.render (node_modules/react-dom/cjs/react-dom.development.js:29670:5)
at node_modules/@testing-library/react-hooks/lib/dom/pure.js:80:18
at act (node_modules/react/cjs/react.development.js:2512:16)
at render (node_modules/@testing-library/react-hooks/lib/dom/pure.js:79:26)
at renderHook (node_modules/@testing-library/react-hooks/lib/core/index.js:114:5)
at Object.
6e334a7a59a383eea9d870c7b1db1859a81ef2fe
Access to script at 'file:///assets/index-ur65-r9T.js' from origin 'null' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, isolated-app, chrome-extension, chrome, https, chrome-untrusted.
ローカルでビルドできたか確認したいがCORSに引っかかってしまう…。ビルドできたらよしとする?
GPTに解析してもらった。Webpackは不要というのは見解が一致しており、試す価値がある。 Babel系は挙動がわかってから取り外したい気もするが、一気に取り外した方がいい。
プロジェクトのpackage.json
ファイルの一部を見ると、Viteに移行した後のスクリプトが設定されていることがわかります。Viteのビルドで不要なライブラリを特定するために、このファイルの残りの部分(特にdependencies
とdevDependencies
セクション)を確認する必要があります。
不要なライブラリを特定する際に考慮すべき点は以下の通りです:
webpack
, webpack-cli
, webpack-dev-server
などのWebpack関連のライブラリは不要になります。続けて、package.json
のdependencies
とdevDependencies
セクションを確認し、不要なライブラリを特定します。
プロジェクトのdependencies
とdevDependencies
を確認したところ、Viteビルドで不要な可能性のあるいくつかのライブラリを特定しました。
Webpack関連のライブラリ:
webpack
webpack-dev-server
webpack-manifest-plugin
workbox-webpack-plugin
html-webpack-plugin
, css-loader
, style-loader
, babel-loader
など)Babel関連のライブラリ:
@babel/core
babel-jest
babel-loader
babel-plugin-named-asset-import
babel-preset-react-app
その他のビルドツール:
css-minimizer-webpack-plugin
terser-webpack-plugin
mini-css-extract-plugin
source-map-loader
resolve-url-loader
eslint-webpack-plugin
@svgr/webpack
case-sensitive-paths-webpack-plugin
これらのライブラリはWebpackやBabelに依存しているか、Webpackのビルドプロセスで使用されるため、Viteを使用する場合には不要になります。ただし、これらのライブラリを削除する前に、プロジェクトのビルドや動作に必要でないことを確認することが重要です。削除を決定したら、package.json
から該当するラインを削除し、依存関係を更新してください。
また、プロジェクトの構成や特定の要件によっては、一部のライブラリがまだ必要になる場合もあるため、慎重に検討することが重要です。
dotenv系とReact系のプラグインはJestが依存しているため削除できない
mofumofu at mofunoMacBook-Air in ~/git/react-sandbox (feature/93-change-vite●)
$ git commit
✔ Preparing lint-staged...
✔ Running tasks for staged files...
✔ Applying modifications from tasks...
✔ Cleaning up temporary files...
[feature/93-change-vite f2fdb4a] delete: #93 babel系のライブラリを削除
2 files changed, 9 insertions(+), 1345 deletions(-)
mofumofu at mofunoMacBook-Air in ~/git/react-sandbox (feature/93-change-vite)
$ npm install
> reactjs-sandbox@1.0.0 prepare
> husky install
husky - Git hooks installed
removed 183 packages, and audited 1170 packages in 6s
203 packages are looking for funding
run `npm fund` for details
4 vulnerabilities (3 moderate, 1 high)
To address all issues, run:
npm audit fix
Run `npm audit` for details.
mofumofu at mofunoMacBook-Air in ~/git/react-sandbox (feature/93-change-vite●)
$ npm run test
> reactjs-sandbox@1.0.0 test
> node scripts/test.js --watchAll=false
node:internal/modules/cjs/loader:1051
throw err;
^
Error: Cannot find module 'react-dev-utils/getPublicUrlOrPath'
Require stack:
- /Users/mofumofu/git/react-sandbox/config/paths.js
- /Users/mofumofu/git/react-sandbox/config/env.js
- /Users/mofumofu/git/react-sandbox/scripts/test.js
at Module._resolveFilename (node:internal/modules/cjs/loader:1048:15)
at Module._load (node:internal/modules/cjs/loader:901:27)
at Module.require (node:internal/modules/cjs/loader:1115:19)
at require (node:internal/modules/helpers:130:18)
at Object.<anonymous> (/Users/mofumofu/git/react-sandbox/config/paths.js:5:28)
at Module._compile (node:internal/modules/cjs/loader:1241:14)
at Module._extensions..js (node:internal/modules/cjs/loader:1295:10)
at Module.load (node:internal/modules/cjs/loader:1091:32)
at Module._load (node:internal/modules/cjs/loader:938:12)
at Module.require (node:internal/modules/cjs/loader:1115:19) {
code: 'MODULE_NOT_FOUND',
requireStack: [
'/Users/mofumofu/git/react-sandbox/config/paths.js',
'/Users/mofumofu/git/react-sandbox/config/env.js',
'/Users/mofumofu/git/react-sandbox/scripts/test.js'
]
}
Node.js v20.9.0
$ npm run test
> reactjs-sandbox@1.0.0 test
> node scripts/test.js --watchAll=false
node:internal/modules/cjs/loader:1051
throw err;
^
Error: Cannot find module 'react-dev-utils/getPublicUrlOrPath'
Require stack:
- /Users/mofumofu/git/react-sandbox/config/paths.js
- /Users/mofumofu/git/react-sandbox/config/env.js
- /Users/mofumofu/git/react-sandbox/scripts/test.js
at Module._resolveFilename (node:internal/modules/cjs/loader:1048:15)
at Module._load (node:internal/modules/cjs/loader:901:27)
at Module.require (node:internal/modules/cjs/loader:1115:19)
at require (node:internal/modules/helpers:130:18)
at Object.<anonymous> (/Users/mofumofu/git/react-sandbox/config/paths.js:5:28)
at Module._compile (node:internal/modules/cjs/loader:1241:14)
at Module._extensions..js (node:internal/modules/cjs/loader:1295:10)
at Module.load (node:internal/modules/cjs/loader:1091:32)
at Module._load (node:internal/modules/cjs/loader:938:12)
at Module.require (node:internal/modules/cjs/loader:1115:19) {
code: 'MODULE_NOT_FOUND',
requireStack: [
'/Users/mofumofu/git/react-sandbox/config/paths.js',
'/Users/mofumofu/git/react-sandbox/config/env.js',
'/Users/mofumofu/git/react-sandbox/scripts/test.js'
]
}
Node.js v20.9.0
https://ja.vitejs.dev/guide/features.html#css-modules https://www.npmjs.com/package/resolve https://www.npmjs.com/package/prompts https://www.npmjs.com/package/react-dev-utils https://www.npmjs.com/package/react-app-polyfill https://github.com/pmmmwh/react-refresh-webpack-plugin https://www.npmjs.com/package/sort-by https://www.npmjs.com/package/semver https://www.npmjs.com/package/identity-obj-proxy https://www.npmjs.com/package/bfj https://www.npmjs.com/package//fs-extra https://www.npmjs.com/package/match-sorter
Create React App (CRA) から Vite への移行時に Storybook を使用していた場合、いくつかの重要な点に注意する必要があります。
StorybookのViteビルダーへの移行:
@storybook/builder-vite
パッケージをインストールし、.storybook/main.js
(または .storybook/main.ts
)ファイルでこのビルダーを指定する必要があります。依存関係の更新:
設定ファイルの調整:
.storybook/main.js
など)を確認し、Vite環境に適した設定に調整する必要がある場合があります。例えば、Webpack固有の設定を削除し、Vite用の設定に置き換えるなどです。プリプロセッサの設定:
カスタムWebpack設定の置き換え:
テスト環境の再構築:
プラグインとアドオンの互換性:
これらの点に注意しながら、Storybookの環境をViteに適合させる作業を進めると良いでしょう。また、移行中に特定の問題に直面した場合は、Storybookのドキュメントやコミュニティからのサポートを求めることをお勧めします。
概要
色々()あって取り替えないといけない場面に当たりそう。 自分のリポジトリも古いので練習も兼ねてやってみる。
まずはTODOをしっかりたてて一気に対応する。 終わったらまとめておきたい。
TODO
アプリ周りの設定
npm install vite @vitejs/plugin-react
でViteとReact用テンプレート導入 https://github.com/MofuMofu2/react-sandbox/commit/58aa1db97155bd9464532dae134f36eab47d61c7<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
のPUBLIC_URL
部分削除npm uninstall react-scripts
でCRA削除 https://github.com/MofuMofu2/react-sandbox/commit/48def3cd247f7b6b1a5c4488452ef6ca702d469esrc/react-app-env.d.ts を src/vite-app-env.d.ts
にリネームREACT_APP_
をVITE_
に置き換えるツール周りの依存を切る
npm run eject
で内部の実行スクリプトを出力 https://github.com/MofuMofu2/react-sandbox/issues/93#issuecomment-1873716178