Reactプロジェクトの始め方|create-react-appは古い?
2025年版React開発環境の構築ガイド。create-react-appの現状から最新のVite、Next.js、Remixまで、目的別の最適なセットアップ方法を解説します。
みなさん、こんなことありませんか?
「create-react-appって、まだ使っていいの?」 「最近よく聞くViteって何?どっちがいいの?」 「Next.jsとかRemix、選択肢多すぎて迷う…」
そんな悩みを抱えていませんか?
React開発環境は2023年以降、大きく変わりました。 長年愛用されてきたcreate-react-app(CRA)が停滞中。 代わりに、もっと速くて現代的な選択肢が人気です。
でも、どれを選べばいいのか分からない。 そんな方も多いはずです。
この記事では、2025年版のReact始め方を解説します。 create-react-appの問題から最新ツールまで。 実際のセットアップ手順も含めて、詳しく説明しますね。
一緒に、現代的なReact環境を作っていきましょう!
create-react-appの現状
まず、従来のcreate-react-appの状況を見てみましょう。 何が問題なのか、理解することが大切です。
create-react-appって何だった?
create-react-app(CRA)は、Reactチームが作った公式ツールでした。 複雑な設定なしで、すぐにReactが始められる画期的なツール。
# 従来は設定が大変でした
npm install react react-dom
npm install --save-dev webpack webpack-cli webpack-dev-server
npm install --save-dev @babel/core @babel/preset-react
npm install --save-dev css-loader style-loader
# さらに多くの設定が必要…
# CRAなら一発で完了
npx create-react-app my-app
cd my-app
npm start
とってもシンプルで便利でしたよね。 でも、時代は変わりました。
CRAの良いところ(過去の話)
// CRAで作成されたプロジェクト構造
my-app/
├── public/
│ ├── index.html
│ └── favicon.ico
├── src/
│ ├── App.js
│ ├── App.css
│ ├── index.js
│ └── index.css
├── package.json
└── README.md
// すぐに使える開発環境
function App() {
return (
<div className="App">
<header className="App-header">
<h1>Hello React!</h1>
</header>
</div>
);
}
export default App;
Hot reload、ES6+、CSS imports、画像処理。 これらが標準で使えました。 初心者にはとても親切でしたね。
何が問題になったの?
1. 遅い、とにかく遅い
# CRAの起動時間
$ npm start
Starting the development server...
Files successfully emitted, waiting for typecheck results...
Issues checking in progress...
No issues found.
webpack compiled with 1 warning
Local: http://localhost:3000
# 初回起動: 15-30秒
# ホットリロード: 2-5秒
# ビルド時間: 30秒-2分
現代の基準では、かなり遅いです。 開発効率が悪くなってしまいました。
2. 古いツールに依存
// CRAのpackage.json(2023年版)
{
"dependencies": {
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-scripts": "5.0.1" // 長期間更新されてない
},
"devDependencies": {
// webpack 4系(最新はwebpack 5)
// Babel設定が古い
// Node.js最新バージョンへの対応遅れ
}
}
技術の進歩に追いついていません。 最新機能が使えないのは困りますよね。
3. カスタマイズが困難
# 設定をカスタマイズするには "eject" が必要
npm run eject
# Warning: この操作は取り消せません
# 設定ファイルが大量に展開される
# 保守が困難になる
ejectすると、もう戻れません。 設定ファイルの山に埋もれることに…
4. 開発チームの問題
- 最後のメジャーアップデート: 2022年
- 未解決のIssue: 1000件以上
- Pull Request: 300件以上が未対応
- 開発者コミュニティからの懸念の声
もはや、積極的に開発されていません。 これは致命的ですよね。
現代のツールとの比較
// 開発体験の違い
const comparison = {
CRA: {
startupTime: '15-30秒',
hotReload: '2-5秒',
bundleSize: '大きい(最適化不十分)',
typeScript: '追加設定が必要',
testing: 'Jest(古いバージョン)'
},
modernTools: {
startupTime: '1-3秒',
hotReload: '即座(100ms以下)',
bundleSize: '小さい(最新最適化)',
typeScript: '標準装備',
testing: '最新テストツール'
}
};
差は歴然ですね。 もう、CRAを選ぶ理由がありません。
CRAから移行すべき場面
- 新規プロジェクト: 必須で移行を検討
- 開発速度に不満: 強く推奨
- TypeScript導入したい: 推奨
- 既存の大規模プロジェクト: 慎重に検討
- 学習目的・小規模: 任意(CRAでも学習には十分)
あなたのプロジェクトはどれに当てはまりますか?
現代的な選択肢を比較してみよう
2025年現在、素晴らしい選択肢がたくさんあります。 それぞれの特徴を詳しく見ていきましょう。
1. Vite - 高速開発の最新ツール
# Viteでプロジェクト作成
npm create vite@latest my-react-app -- --template react
cd my-react-app
npm install
npm run dev
# 起動時間: 1-2秒
# ホットリロード: 即座
Viteの特徴
// vite.config.js - シンプルで強力
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
export default defineConfig({
plugins: [react()],
server: {
port: 3000,
open: true
},
build: {
sourcemap: true,
rollupOptions: {
output: {
manualChunks: {
vendor: ['react', 'react-dom'],
lodash: ['lodash']
}
}
}
}
})
Viteの魅力
- 起動が爆速: ESモジュール活用でほぼ即座
- HMRが超高速: 100ms以下で差分更新
- バンドルサイズ小: Tree-shaking + Rollup最適化
- 設定がシンプル: 分かりやすい設定ファイル
- TypeScript標準: 追加設定なしで使える
- CSS対応: Sass、Less、Stylus対応
// TypeScriptサポート例
interface User {
id: number;
name: string;
email: string;
}
const UserComponent: React.FC<{ user: User }> = ({ user }) => {
return (
<div className="user-card">
<h3>{user.name}</h3>
<p>{user.email}</p>
</div>
);
};
Viteが適している場面
- SPAアプリケーション
- 高速な開発体験が必要
- バンドルサイズを最小化したい
- モダンブラウザをターゲット
- カスタマイズ性を重視
- ライブラリ開発
- プロトタイプ作成
学習や個人開発には、最高の選択肢です。
2. Next.js - Reactフルスタックフレームワーク
# Next.jsプロジェクト作成
npx create-next-app@latest my-nextjs-app
cd my-nextjs-app
npm run dev
# App Router + TypeScript + TailwindCSS + ESLint
Next.jsの特徴
// app/page.tsx - App Router(Next.js 13+)
export default function HomePage() {
return (
<main className="container mx-auto p-4">
<h1 className="text-3xl font-bold">Welcome to Next.js</h1>
<p>Server-side rendering ready!</p>
</main>
);
}
// app/users/[id]/page.tsx - 動的ルーティング
interface Props {
params: { id: string };
}
export default async function UserPage({ params }: Props) {
const user = await fetchUser(params.id); // サーバーサイドで実行
return (
<div>
<h1>{user.name}</h1>
<p>{user.email}</p>
</div>
);
}
// データフェッチもサーバーサイド
async function fetchUser(id: string) {
const response = await fetch(`${process.env.API_URL}/users/${id}`);
return response.json();
}
Next.jsの先進機能
// next.config.js - 豊富な設定オプション
/** @type {import('next').NextConfig} */
const nextConfig = {
experimental: {
appDir: true, // App Router
serverComponents: true // React Server Components
},
images: {
domains: ['example.com'] // 画像最適化
},
async redirects() {
return [
{
source: '/old-page',
destination: '/new-page',
permanent: true,
},
];
}
};
module.exports = nextConfig;
Next.jsが適している場面
- SEOが重要なWebサイト
- サーバーサイドレンダリングが必要
- 静的サイト生成(SSG)
- API routesでバックエンドも構築
- 本格的なWebアプリケーション
- eコマースサイト
- ブログやCMS
- パフォーマンスを重視
企業サイトや本格的なWebアプリには最適です。
3. Remix - データ中心のフルスタック
# Remixプロジェクト作成
npx create-remix@latest my-remix-app
cd my-remix-app
npm run dev
Remixの特徴
// app/routes/users.$userId.tsx
import { json, LoaderFunctionArgs } from "@remix-run/node";
import { useLoaderData } from "@remix-run/react";
// サーバーサイドローダー
export async function loader({ params }: LoaderFunctionArgs) {
const user = await fetchUser(params.userId);
return json({ user });
}
// アクション(フォーム処理)
export async function action({ request }: ActionFunctionArgs) {
const formData = await request.formData();
const name = formData.get("name");
await updateUser({ name });
return redirect("/users");
}
// コンポーネント
export default function UserProfile() {
const { user } = useLoaderData<typeof loader>();
return (
<div>
<h1>{user.name}</h1>
<Form method="post">
<input name="name" defaultValue={user.name} />
<button type="submit">更新</button>
</Form>
</div>
);
}
Remixの革新的な機能
// Progressive Enhancement
// JavaScriptが無効でも動作するフォーム
export default function ContactForm() {
return (
<Form method="post" action="/contact">
<input name="email" type="email" required />
<textarea name="message" required />
<button type="submit">送信</button>
</Form>
);
}
// Error Boundary(ルートレベル)
export function ErrorBoundary() {
return (
<div className="error-container">
<h1>おっと、何かが間違っていました</h1>
<p>申し訳ございませんが、エラーが発生しました。</p>
</div>
);
}
Remixが適している場面:
- データ重視アプリ
- フォーム処理が多い
- Web標準準拠を重視
- Progressive Enhancement
- 管理システム
- CRM、在庫管理
4. T3 Stack - タイプセーフなフルスタック
# T3 Stackプロジェクト作成
npm create t3-app@latest my-t3-app
cd my-t3-app
npm run dev
T3 Stackの構成
// T3 Stackのテクノロジー
const t3Stack = {
frontend: 'Next.js (TypeScript)',
styling: 'TailwindCSS',
database: 'Prisma + PlanetScale/SQLite',
authentication: 'NextAuth.js',
api: 'tRPC(type-safe API)',
deployment: 'Vercel'
};
// tRPCによるタイプセーフAPI
export const postRouter = createTRPCRouter({
getAll: publicProcedure.query(({ ctx }) => {
return ctx.db.post.findMany();
}),
create: protectedProcedure
.input(z.object({
title: z.string().min(1),
content: z.string().min(1),
}))
.mutation(async ({ ctx, input }) => {
return ctx.db.post.create({
data: {
title: input.title,
content: input.content,
authorId: ctx.session.user.id,
},
});
}),
});
// フロントエンドでのタイプセーフな使用
function PostList() {
const { data: posts, isLoading } = api.post.getAll.useQuery();
const createPost = api.post.create.useMutation();
if (isLoading) return <div>Loading...</div>;
return (
<div>
{posts?.map(post => (
<article key={post.id}>
<h2>{post.title}</h2>
<p>{post.content}</p>
</article>
))}
</div>
);
}
T3 Stackが適している場面:
- エンタープライズレベル
- フルタイプセーフティが必要
- チーム開発
- 本格的な企業システム
選択肢比較表
const comparisonTable = {
Vite: {
setup: '★★★★★',
performance: '★★★★★',
features: '★★★☆☆',
learningCurve: '★★☆☆☆',
bestFor: 'SPA、ライブラリ開発'
},
NextJS: {
setup: '★★★★☆',
performance: '★★★★☆',
features: '★★★★★',
learningCurve: '★★★☆☆',
bestFor: 'SEO重視、フルスタック'
},
Remix: {
setup: '★★★☆☆',
performance: '★★★★☆',
features: '★★★★☆',
learningCurve: '★★★★☆',
bestFor: 'データ重視、Web標準'
},
T3Stack: {
setup: '★★★☆☆',
performance: '★★★★☆',
features: '★★★★★',
learningCurve: '★★★★★',
bestFor: 'タイプセーフ、本格開発'
}
};
どれもそれぞれ素晴らしい特徴がありますね。 次は、目的別の選び方を見ていきましょう。
目的別のおすすめツール
プロジェクトの目的に応じて、最適なツールを選んでみましょう。 具体的な使い分け方を解説します。
学習・プロトタイプ作成
おすすめ: Vite
// 学習目的やプロトタイプには Vite が最適
const learningProject = {
tool: 'Vite',
reason: [
'セットアップが最速',
'設定がシンプル',
'React本来の機能に集中できる',
'ホットリロードが高速'
]
};
# セットアップ例
npm create vite@latest my-learning-app -- --template react-ts
cd my-learning-app
npm install
npm run dev
学習に最適なプロジェクト構造:
my-learning-app/
├── src/
│ ├── components/
│ │ ├── Counter.tsx // useState学習
│ │ ├── TodoList.tsx // state管理学習
│ │ └── UserProfile.tsx // props学習
│ ├── hooks/
│ │ ├── useCounter.ts // カスタムフック学習
│ │ └── useLocalStorage.ts
│ ├── App.tsx
│ └── main.tsx
└── package.json
// 学習用コンポーネント例
function LearningApp() {
return (
<div className="learning-app">
<h1>React学習アプリ</h1>
<Counter />
<TodoList />
<UserProfile user={mockUser} />
</div>
);
}
学習にはViteが一番です。 余計な設定に悩まず、Reactに集中できます。
個人プロジェクト・SPA
おすすめ: Vite + React Router
// 個人開発やSPAには Vite + React Router
const spaProject = {
tool: 'Vite + React Router',
additionalLibraries: [
'React Router Dom',
'React Query/TanStack Query',
'Zustand/Context API',
'TailwindCSS'
]
};
プロジェクト例: タスク管理アプリ
my-spa-app/
├── src/
│ ├── pages/
│ │ ├── Dashboard.tsx
│ │ ├── Projects.tsx
│ │ └── Settings.tsx
│ ├── components/
│ │ ├── TaskCard.tsx
│ │ ├── ProjectList.tsx
│ │ └── Navigation.tsx
│ ├── hooks/
│ │ ├── useTasks.ts
│ │ └── useProjects.ts
│ ├── store/
│ │ └── taskStore.ts
│ └── api/
│ └── client.ts
// SPA用のルーティング設定
import { createBrowserRouter, RouterProvider } from 'react-router-dom';
const router = createBrowserRouter([
{
path: '/',
element: <Layout />,
children: [
{ index: true, element: <Dashboard /> },
{ path: 'projects', element: <Projects /> },
{ path: 'projects/:id', element: <ProjectDetail /> },
{ path: 'settings', element: <Settings /> }
]
}
]);
function App() {
return <RouterProvider router={router} />;
}
個人プロジェクトには、自由度の高いViteがピッタリです。
ビジネスサイト・ブログ
おすすめ: Next.js
// SEOが重要なサイトには Next.js
const businessWebsite = {
tool: 'Next.js',
features: [
'SSG(静的サイト生成)',
'Image最適化',
'SEO対応',
'サイトマップ自動生成'
]
};
ビジネスサイト構造例:
my-business-site/
├── app/
│ ├── (marketing)/
│ │ ├── page.tsx // ホームページ
│ │ ├── about/page.tsx // 会社概要
│ │ ├── services/page.tsx // サービス
│ │ └── contact/page.tsx // お問い合わせ
│ ├── blog/
│ │ ├── page.tsx // ブログ一覧
│ │ └── [slug]/page.tsx // 記事詳細
│ ├── components/
│ │ ├── Header.tsx
│ │ ├── Footer.tsx
│ │ └── ContactForm.tsx
│ └── layout.tsx
// SEO最適化例
export const metadata: Metadata = {
title: '株式会社サンプル | Webソリューション',
description: 'モダンなWeb開発でビジネスの成長をサポートします',
keywords: 'Web開発, React, Next.js, SEO',
openGraph: {
title: '株式会社サンプル',
description: 'モダンなWeb開発でビジネスの成長をサポート',
images: ['/og-image.jpg']
}
};
SEOが重要なサイトには、Next.jsが最強です。
Eコマース・複雑なWebアプリ
おすすめ: Next.js + 追加ツール
// 複雑なアプリケーションには Next.js + 追加ツール
const ecommerceApp = {
tool: 'Next.js',
additionalTools: [
'Prisma(DB ORM)',
'NextAuth.js(認証)',
'Stripe(決済)',
'Vercel(ホスティング)'
]
};
Eコマース構造例:
my-ecommerce/
├── app/
│ ├── (shop)/
│ │ ├── page.tsx // 商品一覧
│ │ ├── products/[id]/page.tsx // 商品詳細
│ │ ├── cart/page.tsx // カート
│ │ └── checkout/page.tsx // 決済
│ ├── (auth)/
│ │ ├── login/page.tsx
│ │ └── register/page.tsx
│ ├── (admin)/
│ │ ├── dashboard/page.tsx
│ │ └── products/page.tsx
│ ├── api/
│ │ ├── products/route.ts
│ │ ├── orders/route.ts
│ │ └── stripe/route.ts
│ └── components/
│ ├── ProductCard.tsx
│ ├── CartItem.tsx
│ └── CheckoutForm.tsx
// API Routes例(決済処理)
import { NextRequest, NextResponse } from 'next/server';
import Stripe from 'stripe';
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!);
export async function POST(request: NextRequest) {
try {
const { amount, currency = 'jpy' } = await request.json();
const paymentIntent = await stripe.paymentIntents.create({
amount,
currency,
metadata: {
order_id: generateOrderId()
}
});
return NextResponse.json({
client_secret: paymentIntent.client_secret
});
} catch (error) {
return NextResponse.json(
{ error: 'Payment intent creation failed' },
{ status: 500 }
);
}
}
本格的なWebアプリには、Next.jsの豊富な機能が活躍します。
データ重視のアプリケーション
おすすめ: Remix
// データ操作が多いアプリには Remix
const dataIntensiveApp = {
tool: 'Remix',
strengths: [
'フォーム処理に特化',
'サーバーサイドバリデーション',
'Progressive Enhancement',
'ネストされたルーティング'
],
example: '顧客管理システム、在庫管理、CRM'
};
// Remixでのデータ処理例
export async function loader({ params }: LoaderFunctionArgs) {
const customer = await getCustomer(params.customerId);
if (!customer) throw new Response("Not Found", { status: 404 });
return json({ customer });
}
export async function action({ request, params }: ActionFunctionArgs) {
const formData = await request.formData();
const updates = Object.fromEntries(formData);
// サーバーサイドバリデーション
const errors = validateCustomerData(updates);
if (errors) {
return json({ errors }, { status: 400 });
}
await updateCustomer(params.customerId, updates);
return redirect(`/customers/${params.customerId}`);
}
export default function EditCustomer() {
const { customer } = useLoaderData<typeof loader>();
const actionData = useActionData<typeof action>();
return (
<Form method="post">
<input
name="name"
defaultValue={customer.name}
aria-invalid={actionData?.errors?.name ? true : undefined}
/>
{actionData?.errors?.name && (
<span className="error">{actionData.errors.name}</span>
)}
<button type="submit">更新</button>
</Form>
);
}
フォーム処理やデータ管理が多いなら、Remixが最適です。
本格的な企業アプリケーション
おすすめ: T3 Stack
// エンタープライズレベルには T3 Stack
const enterpriseApp = {
tool: 'T3 Stack',
benefits: [
'フルタイプセーフティ',
'スケーラブルな構造',
'モダンなツールチェーン',
'チーム開発に最適'
],
examples: [
'社内ダッシュボード',
'プロジェクト管理システム',
'顧客管理システム',
'レポーティングツール'
]
};
企業レベルのアプリには、型安全性とスケーラビリティが重要です。
選択フローチャート
// プロジェクト選択のフローチャート
function selectTool(requirements) {
if (requirements.purpose === 'learning') {
return 'Vite';
}
if (requirements.seo === false && requirements.type === 'spa') {
return 'Vite + React Router';
}
if (requirements.seo === true) {
if (requirements.complexity === 'simple') {
return 'Next.js';
}
if (requirements.dataProcessing === 'heavy') {
return 'Remix';
}
}
if (requirements.teamSize > 5 && requirements.typeScript === true) {
return 'T3 Stack';
}
// デフォルト推奨
return 'Next.js';
}
// 使用例
const projectRequirements = {
purpose: 'business',
seo: true,
complexity: 'medium',
dataProcessing: 'light',
teamSize: 3,
typeScript: true
};
const recommendedTool = selectTool(projectRequirements);
console.log(`推奨ツール: ${recommendedTool}`);
あなたのプロジェクトにはどれが合いそうですか?
実践:Viteでプロジェクト作成
最も汎用性が高いViteを使って、実際にプロジェクトを作ってみましょう。 手順を詳しく解説します。
基本セットアップ
# 1. プロジェクト作成
npm create vite@latest my-react-app -- --template react-ts
cd my-react-app
# 2. 依存関係のインストール
npm install
# 3. 開発サーバー起動
npm run dev
# 出力例:
# VITE v5.0.0 ready in 200 ms
# ➜ Local: http://localhost:5173/
# ➜ Network: use --host to expose
たった3ステップで完了! この速さがViteの魅力ですね。
生成されるプロジェクト構造
my-react-app/
├── public/
│ └── vite.svg
├── src/
│ ├── assets/
│ │ └── react.svg
│ ├── App.css
│ ├── App.tsx
│ ├── index.css
│ ├── main.tsx
│ └── vite-env.d.ts
├── index.html
├── package.json
├── tsconfig.json
├── tsconfig.node.json
└── vite.config.ts
シンプルで分かりやすい構造です。
初期ファイルの理解
// main.tsx - アプリケーションのエントリーポイント
import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App.tsx'
import './index.css'
ReactDOM.createRoot(document.getElementById('root')!).render(
<React.StrictMode>
<App />
</React.StrictMode>,
)
// App.tsx - メインコンポーネント
import { useState } from 'react'
import reactLogo from './assets/react.svg'
import viteLogo from '/vite.svg'
import './App.css'
function App() {
const [count, setCount] = useState(0)
return (
<>
<div>
<a href="https://vitejs.dev" target="_blank">
<img src={viteLogo} className="logo" alt="Vite logo" />
</a>
<a href="https://react.dev" target="_blank">
<img src={reactLogo} className="logo react" alt="React logo" />
</a>
</div>
<h1>Vite + React</h1>
<div className="card">
<button onClick={() => setCount((count) => count + 1)}>
count is {count}
</button>
<p>
Edit <code>src/App.tsx</code> and save to test HMR
</p>
</div>
</>
)
}
export default App
すでに動くアプリができています。 TypeScriptも標準で使えますね。
必要なライブラリの追加
# ルーティング
npm install react-router-dom
npm install -D @types/react-router-dom
# 状態管理
npm install zustand
# データフェッチ
npm install @tanstack/react-query
# UI/スタイリング
npm install tailwindcss postcss autoprefixer
npm install lucide-react # アイコンライブラリ
# フォーム
npm install react-hook-form @hookform/resolvers
npm install zod # バリデーション
# ユーティリティ
npm install clsx # クラス名の条件付き結合
npm install date-fns # 日付操作
よく使うライブラリを一気に追加しましょう。
TailwindCSSのセットアップ
# TailwindCSS初期化
npx tailwindcss init -p
// tailwind.config.js
/** @type {import('tailwindcss').Config} */
export default {
content: [
"./index.html",
"./src/**/*.{js,ts,jsx,tsx}",
],
theme: {
extend: {},
},
plugins: [],
}
/* src/index.css に追加 */
@tailwind base;
@tailwind components;
@tailwind utilities;
これで、TailwindCSSが使えるようになりました。
プロジェクト構造の改善
// より実践的なプロジェクト構造
src/
├── components/ # 再利用可能コンポーネント
│ ├── ui/ # 基本UIコンポーネント
│ │ ├── Button.tsx
│ │ ├── Input.tsx
│ │ └── Modal.tsx
│ ├── layout/ # レイアウトコンポーネント
│ │ ├── Header.tsx
│ │ ├── Footer.tsx
│ │ └── Sidebar.tsx
│ └── common/ # 共通コンポーネント
│ ├── Loading.tsx
│ └── ErrorBoundary.tsx
├── pages/ # ページコンポーネント
│ ├── Home.tsx
│ ├── About.tsx
│ └── Contact.tsx
├── hooks/ # カスタムフック
│ ├── useAuth.ts
│ ├── useApi.ts
│ └── useLocalStorage.ts
├── store/ # 状態管理
│ ├── authStore.ts
│ └── appStore.ts
├── api/ # API関連
│ ├── client.ts
│ └── endpoints.ts
├── types/ # TypeScript型定義
│ ├── auth.ts
│ └── api.ts
├── utils/ # ユーティリティ関数
│ ├── format.ts
│ └── validation.ts
└── styles/ # スタイルファイル
├── globals.css
└── components.css
実際のプロジェクトでは、この構造がおすすめです。
ルーティングの設定
// src/App.tsx - React Router設定
import { BrowserRouter, Routes, Route } from 'react-router-dom';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import Layout from './components/layout/Layout';
import Home from './pages/Home';
import About from './pages/About';
import Contact from './pages/Contact';
import NotFound from './pages/NotFound';
const queryClient = new QueryClient();
function App() {
return (
<QueryClientProvider client={queryClient}>
<BrowserRouter>
<Routes>
<Route path="/" element={<Layout />}>
<Route index element={<Home />} />
<Route path="about" element={<About />} />
<Route path="contact" element={<Contact />} />
<Route path="*" element={<NotFound />} />
</Route>
</Routes>
</BrowserRouter>
</QueryClientProvider>
);
}
export default App;
// src/components/layout/Layout.tsx
import { Outlet } from 'react-router-dom';
import Header from './Header';
import Footer from './Footer';
export default function Layout() {
return (
<div className="min-h-screen flex flex-col">
<Header />
<main className="flex-1 container mx-auto px-4 py-8">
<Outlet />
</main>
<Footer />
</div>
);
}
ルーティングとレイアウトの基本構造ができました。
状態管理の設定(Zustand)
// src/store/authStore.ts
import { create } from 'zustand';
import { persist } from 'zustand/middleware';
interface User {
id: string;
name: string;
email: string;
}
interface AuthState {
user: User | null;
isAuthenticated: boolean;
login: (email: string, password: string) => Promise<void>;
logout: () => void;
updateUser: (user: Partial<User>) => void;
}
export const useAuthStore = create<AuthState>()(
persist(
(set, get) => ({
user: null,
isAuthenticated: false,
login: async (email: string, password: string) => {
try {
// API呼び出し
const response = await fetch('/api/auth/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ email, password })
});
const user = await response.json();
set({
user,
isAuthenticated: true
});
} catch (error) {
console.error('Login failed:', error);
throw error;
}
},
logout: () => {
set({
user: null,
isAuthenticated: false
});
},
updateUser: (updates: Partial<User>) => {
const currentUser = get().user;
if (currentUser) {
set({
user: { ...currentUser, ...updates }
});
}
}
}),
{
name: 'auth-storage', // localStorage key
partialize: (state) => ({
user: state.user,
isAuthenticated: state.isAuthenticated
})
}
)
);
Zustandで状態管理も簡単にできます。
APIクライアントの設定
// src/api/client.ts
import { QueryClient } from '@tanstack/react-query';
const API_BASE_URL = import.meta.env.VITE_API_URL || 'http://localhost:3001/api';
class ApiClient {
private baseURL: string;
constructor(baseURL: string) {
this.baseURL = baseURL;
}
private async request<T>(
endpoint: string,
options: RequestInit = {}
): Promise<T> {
const url = `${this.baseURL}${endpoint}`;
const config: RequestInit = {
headers: {
'Content-Type': 'application/json',
...options.headers,
},
...options,
};
// 認証トークンを自動付与
const token = localStorage.getItem('auth-token');
if (token) {
config.headers = {
...config.headers,
Authorization: `Bearer ${token}`,
};
}
const response = await fetch(url, config);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return response.json();
}
get<T>(endpoint: string): Promise<T> {
return this.request<T>(endpoint);
}
post<T>(endpoint: string, data: any): Promise<T> {
return this.request<T>(endpoint, {
method: 'POST',
body: JSON.stringify(data),
});
}
put<T>(endpoint: string, data: any): Promise<T> {
return this.request<T>(endpoint, {
method: 'PUT',
body: JSON.stringify(data),
});
}
delete<T>(endpoint: string): Promise<T> {
return this.request<T>(endpoint, {
method: 'DELETE',
});
}
}
export const apiClient = new ApiClient(API_BASE_URL);
// src/hooks/useApi.ts - React Query と組み合わせ
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { apiClient } from '../api/client';
export function useUsers() {
return useQuery({
queryKey: ['users'],
queryFn: () => apiClient.get('/users')
});
}
export function useCreateUser() {
const queryClient = useQueryClient();
return useMutation({
mutationFn: (userData: any) => apiClient.post('/users', userData),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['users'] });
}
});
}
API連携の基盤も整いました。
環境変数の設定
# .env.local
VITE_API_URL=http://localhost:3001/api
VITE_APP_NAME=My React App
VITE_VERSION=1.0.0
# .env.production
VITE_API_URL=https://api.myapp.com
VITE_APP_NAME=My React App
VITE_VERSION=1.0.0
// src/config/env.ts - 環境変数の型安全な使用
interface Environment {
apiUrl: string;
appName: string;
version: string;
isDevelopment: boolean;
isProduction: boolean;
}
export const env: Environment = {
apiUrl: import.meta.env.VITE_API_URL || 'http://localhost:3001/api',
appName: import.meta.env.VITE_APP_NAME || 'React App',
version: import.meta.env.VITE_VERSION || '1.0.0',
isDevelopment: import.meta.env.DEV,
isProduction: import.meta.env.PROD,
};
環境変数も型安全に管理できます。
ビルドと最適化
// vite.config.ts - 本番用最適化設定
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import { resolve } from 'path'
export default defineConfig({
plugins: [react()],
// パスエイリアス
resolve: {
alias: {
'@': resolve(__dirname, 'src'),
'@components': resolve(__dirname, 'src/components'),
'@pages': resolve(__dirname, 'src/pages'),
'@hooks': resolve(__dirname, 'src/hooks'),
'@store': resolve(__dirname, 'src/store'),
'@api': resolve(__dirname, 'src/api'),
'@types': resolve(__dirname, 'src/types'),
'@utils': resolve(__dirname, 'src/utils'),
}
},
// ビルド最適化
build: {
sourcemap: true,
rollupOptions: {
output: {
manualChunks: {
vendor: ['react', 'react-dom'],
router: ['react-router-dom'],
query: ['@tanstack/react-query'],
ui: ['lucide-react']
}
}
}
},
// 開発サーバー設定
server: {
port: 3000,
open: true,
proxy: {
'/api': {
target: 'http://localhost:3001',
changeOrigin: true
}
}
}
})
最適化設定もバッチリです。
これで、Viteを使ったモダンなReact開発環境が完成しました! 高速で柔軟な開発ができますね。
まとめ:今すぐ始めよう
2025年版のReactプロジェクトの始め方を解説しました。 最後に、重要なポイントをまとめます。
重要なポイント
1. create-react-appの現状
- 開発・保守の停滞により、現在は推奨されない
- 起動が遅く、古いツールチェインに依存
- カスタマイズが困難で、モダンな開発体験を提供できない
2. 現代的な代替手段
Vite:
- 最高の開発体験(1-2秒起動、即座のHMR)
- シンプルな設定、柔軟なカスタマイズ
- SPA、学習、プロトタイプに最適
Next.js:
- フルスタックフレームワーク
- SSR、SSG、SEO対応
- 本格的なWebアプリケーションに最適
Remix:
- データ中心のアプローチ
- Web標準準拠、Progressive Enhancement
- フォーム処理が多いアプリに最適
T3 Stack:
- フルタイプセーフティ
- エンタープライズ級の開発スタック
- 大規模チーム開発に最適
選択指針
// プロジェクトタイプ別の推奨ツール
const recommendationMap = {
学習: 'Vite',
プロトタイプ: 'Vite',
SPA: 'Vite + React Router',
ビジネスサイト: 'Next.js',
ブログ: 'Next.js',
eコマース: 'Next.js',
データ管理システム: 'Remix',
企業アプリケーション: 'T3 Stack'
};
実践的なアドバイス
新規プロジェクト
- まずはViteで始めて、要件に応じて他のツールを検討
- TypeScriptを標準で使用
- TailwindCSSでスタイリング効率化
既存プロジェクト
- CRAプロジェクトの移行は段階的に検討
- まずは新機能から新しいツールを試用
- 移行コストと利益を慎重に比較
学習アプローチ
- Viteで基本を学習
- 要件に応じてNext.jsやRemixを習得
- 最終的にT3 Stackで本格開発
最終的な推奨コマンド
初心者・学習目的:
npm create vite@latest my-app -- --template react-ts
ビジネス・SEO重視:
npx create-next-app@latest my-app --typescript --tailwind --app
データ重視・フォーム多用:
npx create-remix@latest my-app
エンタープライズ・チーム開発:
npm create t3-app@latest my-app
今後の動向
2025年注目の技術:
- Viteの更なる普及
- Next.js App Routerの成熟
- RemixとReact Routerの統合
- React Server Componentsの標準化
新技術:
- Turbopack(Next.jsの新バンドラー)
- SWC(Rustベースのコンパイラ)
- React Compiler(自動最適化)
- Suspense for Data Fetching
継続的な学習
- 公式ドキュメント:各ツールの最新情報をチェック
- コミュニティ:Discord、Reddit、Twitterで情報収集
- 実践:小さなプロジェクトで新しいツールを試用
- ベンチマーク:定期的にパフォーマンスを測定・比較
最後に
React開発環境は急速に進化しています。 create-react-appの時代は終わりました。
でも、それに代わる素晴らしい選択肢がたくさんあります。 プロジェクトの要件を明確にして、適切なツールを選びましょう。
より効率的で現代的なReact開発が実現できます。
みなさんの開発が、もっと楽しく効率的になりますように! ぜひ、新しいツールにチャレンジしてみてくださいね。