Skip to content

React エコシステム 2025 年全景:状態管理・ビルドツール・CSS・テスト

2025年のReactエコシステムは多岐にわたって発展しています。本記事では状態管理、ビルドツール、CSS-in-JS、テストの4つの領域の現状を整理し、プロジェクト選択の参考にします。

状態管理:Server ActionsとSignalの台頭でクライアント状態が変わる

2025年のReact状態管理の最大のトレンドは「サーバー状態とクライアント状態の明確な分離」です。

サーバー状態:TanStack Query / SWR が依然強い

typescript
// TanStack Query v5 + Server Actions の組み合わせ
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";

function TodoList() {
  const queryClient = useQueryClient();

  const { data: todos } = useQuery({
    queryKey: ["todos"],
    queryFn: () => fetchTodos(), // Server Action または API fetch
    staleTime: 5 * 60 * 1000, // 5分間は再フェッチしない
  });

  const createMutation = useMutation({
    mutationFn: createTodo, // Server Action
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ["todos"] });
    },
    onMutate: async (newTodo) => {
      // 楽観的更新
      await queryClient.cancelQueries({ queryKey: ["todos"] });
      const prev = queryClient.getQueryData(["todos"]);
      queryClient.setQueryData(["todos"], (old: Todo[]) => [...old, { ...newTodo, id: "temp" }]);
      return { prev };
    },
    onError: (_, __, context) => {
      queryClient.setQueryData(["todos"], context?.prev);
    },
  });

  return (/* ... */);
}

クライアント状態:Zustand vs Jotai vs Signals

typescript
// Zustand:シンプルなストア(依然として人気)
import { create } from "zustand";

const useCartStore = create<CartState>((set, get) => ({
  items: [],
  addItem: (item) => set((state) => ({ items: [...state.items, item] })),
  total: () => get().items.reduce((sum, item) => sum + item.price, 0),
}));

// Jotai:アトムベース(コンポーネントレベルの状態に向いている)
import { atom, useAtom } from "jotai";

const cartAtom = atom<CartItem[]>([]);
const cartTotalAtom = atom((get) => get(cartAtom).reduce((sum, item) => sum + item.price, 0));

function CartBadge() {
  const total = useAtomValue(cartTotalAtom);
  return <span>{total}</span>;
}

ビルドツール:Vite 6 + Turbopack の競争

2025年ビルドツールの勢力図:

ツール          採用率  ホットな機能
────────────────────────────────────────────────────
Vite 6          ★★★★★  Environment API、Rolldown Preview
Turbopack       ★★★★   Next.js 15+でデフォルト、Rustベース高速
Rspack 2        ★★★    Webpackエコシステムとの互換性
esbuild         ★★★    依然として最速、バンドル機能は限定的
Rolldown        ★★     Oxc Rust、Vite 7での採用を見込む
typescript
// vite.config.ts — 2025 年の推奨設定
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";

export default defineConfig({
  plugins: [
    react({
      babel: {
        plugins: [["babel-plugin-react-compiler"]], // React Compiler 有効化
      },
    }),
  ],
  build: {
    // コード分割の最適化
    rollupOptions: {
      output: {
        manualChunks: {
          vendor: ["react", "react-dom"],
          query: ["@tanstack/react-query"],
          router: ["react-router-dom"],
        },
      },
    },
  },
});

CSS-in-JS:ランタイムコストゼロへの移行

2025年のReact向けCSS-in-JSの選択肢は「ゼロランタイム」へシフトしています。

typescript
// ゼロランタイム CSS-in-JS の選択肢

// 1. vanilla-extract — TypeScript フレンドリー、ビルド時に CSS ファイルへ変換
import { style } from "@vanilla-extract/css";

export const button = style({
  padding: "8px 16px",
  borderRadius: "4px",
  selectors: {
    "&:hover": { opacity: 0.8 },
  },
  "@media": {
    "(max-width: 768px)": { padding: "6px 12px" },
  },
});

// 2. Panda CSS — Tailwind ライクな DX、ゼロランタイム
import { css } from "../styled-system/css";

function Button() {
  return (
    <button className={css({ px: "4", py: "2", rounded: "md", _hover: { opacity: 0.8 } })}>
      クリック
    </button>
  );
}

// 3. Tailwind CSS 4(CSS-first config)— 設定を CSS ファイルに移動
// @import "tailwindcss";
// @theme { --color-brand: #0066cc; }

テスト:Vitestの一強

typescript
// vitest.config.ts — 2025 年の推奨テスト設定
import { defineConfig } from "vitest/config";
import react from "@vitejs/plugin-react";

export default defineConfig({
  plugins: [react()],
  test: {
    environment: "jsdom",
    globals: true,
    setupFiles: ["./src/test-setup.ts"],
    coverage: {
      provider: "v8",
      reporter: ["text", "lcov"],
      exclude: ["**/*.d.ts", "**/*.config.*"],
    },
  },
});
typescript
// React Testing Library + Vitest(2025年の標準スタック)
import { render, screen, fireEvent, waitFor } from "@testing-library/react";
import { describe, it, expect, vi } from "vitest";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { TodoList } from "./TodoList";

function renderWithProviders(ui: React.ReactElement) {
  const queryClient = new QueryClient({
    defaultOptions: { queries: { retry: false } },
  });
  return render(
    <QueryClientProvider client={queryClient}>{ui}</QueryClientProvider>
  );
}

describe("TodoList", () => {
  it("Todoを追加できる", async () => {
    renderWithProviders(<TodoList />);

    const input = screen.getByPlaceholderText("新しいTodo...");
    fireEvent.change(input, { target: { value: "テストTodo" } });
    fireEvent.click(screen.getByRole("button", { name: "追加" }));

    await waitFor(() => {
      expect(screen.getByText("テストTodo")).toBeInTheDocument();
    });
  });
});

2025年のReact技術スタック推奨

用途            推奨スタック
────────────────────────────────────────────────────
Webアプリ       Next.js 16 + TanStack Query + Zustand + Tailwind CSS 4
静的サイト      Vite + React Router v7 + vanilla-extract
モバイル        Expo SDK 52 + Expo Router v4 + NativeWind
エンタープライズ Next.js 16 + TanStack Query + Jotai + Panda CSS
テスト          Vitest + Testing Library + Playwright + MSW

まとめ

2025年のReactエコシステムは成熟しています——React Compilerによるメモ化の自動化、Server Actionsによるフルスタック統合、ゼロランタイムCSSによるパフォーマンス改善と、フロントエンド開発の主要な課題に対して洗練されたソリューションが揃ってきました。新規プロジェクトはこれらのベストプラクティスを組み合わせることで、高いパフォーマンスと良好なDXを同時に実現できます。

MIT Licensed