はじめに
既存案件ではもっぱら Create React App(以下CRA) を利用してReactプロジェクトを作成していたが、オワコン的風潮をよく聞く&いつの間にかReact公式ドキュメントでも取り上げられなくなっている(リンク先参照)。
「Next.jsとかではなく素のReactで開発したい、けどCRAは使わない方が良さそう……」
ということでViteに乗り換えてみたら、開発体験が凄まじく向上。
開発サーバー立ち上げが早い、ビルドも早い、なのでデプロイワークフローも短縮できた、細かい設定も簡単……。
「何がどうしてこんなに違うんだ!?」
ということで、改めてCRAの挙動と🤔な点についてまとめた上で、Viteの特徴を整理してみた。
本記事では、CRAからViteに乗り換える等の手法については触れません。
CRAとViteの開発体験について、「開発サーバー」「ビルドツール」「設定のカスタマイズ性」といった観点から比較メモしただけです。
CRAの概要
Create React App(CRA)は、Facebook が開発した React アプリケーションのセットアップを簡単にするためのツール。
少し前まではReact公式ドキュメントの「新しいReactアプリを作る」の段でも使用されており、Udemy等の動画教材でも CRA を用いて開発環境を構築しているケースが多い。
主な特徴
React環境のセットアップ
以下のコマンドを実行するだけで、React の初期構成が自動的に生成され、新しいプロジェクトが完成する。
プロジェクトの構成やビルドツールの設定も CRA が自動で行ってくれるので、開発者はすぐにコーディングをスタートできる。
# JavaScript
npx create-react-app my-app
# TypeScriptScript
npx create-react-app my-app --template typescript
作成された新規プロジェクトは、デフォルトで以下のツールや設定を含んでいる。
-
Webpack
- モジュールバンドラ。複数のJavaScriptを1つにまとめ、処理を最適化する。
-
Babel
- JavaScript のトランスパイラ。最新の JavaScript 機能を古いブラウザでもサポートできるようにする。
-
ESLint
- コードの静的解析ツール。
-
Jest
- テスト用フレームワーク。単体テストやスナップショットテストなどで利用する。
開発サーバーとホットリロード
webpack-dev-server を用いることで、開発中の変更をリアルタイムでブラウザに反映するホットリロード機能を提供する。
コードを変更して保存すると、webpack-dev-server が差分を検知してコンパイルを実行。Web サーバーが自動的にリロードされる。変更のたびに毎回、手動でビルドをしなくて済むので、開発体験が向上する。
※参照:Webpack公式
ビルドツール
build
ディレクトリ内にバンドルファイルが出力される。
コンパイルはbabelで、バンドルはwebpackで実現。
上記記事によると、CRAによるReact構成の場合、ビルドは以下の流れで実行されるとのこと。
- Webpack のプラグイン
fork-ts-checker-webpack-plugin
が型チェックを行う- Webpack のプラグイン
babel-loader
が Babel の@babel/preset-react
を使ってコンパイルを行い、JSX や TypeScript を JavaScript に変換する- Webpack がbuildフォルダ配下にバンドルしたファイルを出力する
Create React App の問題点
ビルド速度と開発サーバーのパフォーマンス
-
ビルド速度:
Webpack
は、大規模なプロジェクトや多くの依存関係がある場合、ビルド速度が遅くなることがある。特に本番ビルドはかなり時間を要することも。 -
開発サーバーのパフォーマンス:
webpack-dev-server
のホットリロード機能は、プロジェクト規模によっては画面更新に時間がかかる場合も多い。自PJTでも、ソースコード変更後5秒くらいしてから画面が更新されていた。
また初期起動にもかなり時間を要する。アプリの規模にもよるが、開発サーバのポートが開くまで30秒~1分超待機することもままある。
設定のカスタマイズ性
デフォルトの構成をカスタマイズすることが困難。例えば「絶対パス&エイリアスによるインポートをしたい!」と思っても、デフォルトの設定だと無理。
eject
コマンドを実行すれば設定ファイルを手動で設定できるが、結構複雑難解。
「ejectなしでCRAアプリをカスタマイズできるよ!」を謳うcraco
なんてツールが登場する程度には難しい。
デフォルト設定が過剰
CRA は、多くのデフォルト設定や機能を含んでいるが、これが時折過剰。プロジェクトによっては不要な設定が含まれることもある。
メンテが滞っている
CRAの最新バージョンはv5.0.1。これのリリース日は2022年4月12日。2年以上経過してしまっている。
その間にCRAの依存パッケージは更新されている。がCRAはメンテができていない。そのため、今CRAで新規プロジェクトを作成すると、依存パッケージのバージョン関連でwarningが出てくる。
Viteの概要
Viteは、最新の Web プロジェクト向けに、より高速で無駄のない開発エクスペリエンスを提供することを目的としたビルド ツール。
(フランス語で「速い」という意味の単語から来ているらしい。読みは「ビート」)
Evan You(Vue.js の創設者)によって開発され、最初は Vue.js をターゲットにしていたが、現在では React や他のフレームワークにも対応。
React公式でも、Next.jsなどのフレームワークを使用しない場合の選択肢としてViteが挙げられている。
Vite で React を開発するメリット
超高速な開発サーバー
Vite は開発速度を重視して設計されており、開発サーバーが標準で組み込まれている。超高速。
CRA構成だと30~60秒近くかかっていた開発サーバーの初回起動も、10秒足らずで完了するくらいには高速。
Vite では、アプリケーションのモジュールを 依存関係(開発中あまり変更されない)とソースコード(開発中頻繁に変更される) の2種に分割している。
前者の依存関係は、esbuild
を使用して事前にバンドルし、node_modules/.vite
にキャッシュする。
esbuild
はWebpack
よりも 100 倍高速に動作するらしい(esbuild公式参照)
後者のソースコード は、開発サーバーとしてバンドルはせず、ブラウザのNative ES Modulesを使用して画面描画する。
Vite はブラウザーのリクエストに応じて、ソースコードを変換し提供するだけ。開発サーバー起動時にJSのバンドルを行わないので、ファイルの変換やバンドルのオーバーヘッドが削減され、開発サーバーの超高速化が実現できている。
ホットリロードも高速。こちらもブラウザのNative ES Modulesを使用し、高速化を実現。
修正分のみを即時にモジュール単位で変更してくれて、開発体験爆上がり。
ファイルが編集されたとき、Vite は編集されたモジュールと最も近い HMR バウンダリ間のつながりを正確に無効化することで(大抵はモジュール本体だけです)、HMR による更新はアプリケーションのサイズに関係なく一貫して高速で実行されます。
Vite は esbuild を用いて TypeScript を JavaScript に変換します。これは、vanilla の tsc よりも約 20〜30 倍速く、HMR の更新は 50 ミリ秒未満でブラウザーに反映されます
超高速なビルド
プロダクションビルド時には、Rollup
を使用して最適化されたバンドルを生成。
Rollup は ES Modules(import/export)の仕組みを活かしてバンドルを行う。従来のCommonJSベースのやり方に比べ、より効率的にバンドルを実行できるらしい。
また、ツリーシェイキング(コードを分析し、最終的なバンドルから未使用のコードやデッドコードを排除すること)などの機能によって、さらにバンドルサイズを小さくすることもできている。
実際、自PJTでは、CRA構成だと12分程度かかっていたデプロイワークフローが、Vite移行後5~7分程度にまで短縮された。
簡単セットアップ&簡単カスタマイズ
React プロジェクトを迅速にセットアップするためのテンプレートを提供しており、以下のコマンドで新しいプロジェクトを簡単に作成可能。
npm create vite@latest my-react-app --template react
cd my-react-app
npm install
npm run dev
Vite の設定ファイル(vite.config.ts または vite.config.js)は、非常にシンプルで柔軟。
下記のような具合でConfigオブジェクトをエクスポートするだけなので、必要に応じてプラグインを追加したり、設定をカスタマイズしたりするのも容易。
絶対パスインポート設定とかも簡単にできた。
// https://vitejs.dev/config/
export default defineConfig({
plugins: [react(), tsconfigPaths(), TanStackRouterVite(), svgr()],
resolve: {
alias: {
"~": path.resolve(__dirname, "./src/"), // 絶対パスインポート設定
},
},
base: "/",
build: {
outDir: "dist",
},
});
終わりに
CRAとViteは、「できること」や「使われ方」は類似しているが、実際にやっていることや設計思想は全く異なる模様。
Reactテンプレートを作成するツールであるCRAに対し、Viteはビルドツールであるため、開発体験に関してはかなり画期的かつ魅力的な面が多い。
これから新しくReactのプロジェクトを作成するのであれば、まずCRAではなくViteを使う方がベターであると思うが、Viteの何が画期的なのかを理解する上で、CRAという旧来のツールと比較してみるというのも結構おもしろいかもしれない。