🏃

Remix v2 から React Router v7 への移行情報まとめ(2025年1月時点)

2025/01/01に公開

以下はRemix v2からReact Router v7への移行を検討にするに際してまとめた情報です。

1. 背景と概要

  • React Router v7 は 2024 年 11 月 22 日にリリースされ、Remix v2 の機能を統合
  • もともと Remix は React Router をベースにしたフルスタックフレームワーク
  • 「Remix v3」として予定されていた機能が「React Router v7」として提供
  • React Router v7 はルーティングライブラリからフルスタックフレームワークへ進化

2. 主な変更点

2.1 ルーティング方式

コンフィグベースルーティング

// app/routes.ts
import {
  type RouteConfig,
  route,
  index,
  layout,
} from "@react-router/dev/routes";

export const routes: RouteConfig = [
  index("./home.tsx"),
  route("about", "./about.tsx"),
  layout("./auth/layout.tsx", [
    route("login", "./auth/login.tsx"),
    route("register", "./auth/register.tsx"),
  ]),
];

ファイルベースルーティング

  • @react-router/fs-routes を使用して Remix v2 同様のファイルベースルーティングも可能
import { flatRoutes } from "@react-router/fs-routes";
export default flatRoutes() satisfies RouteConfig;

2.2 型安全性の向上

  • ルートごとの型が自動生成される
  • useLoaderData や useActionData の型補完が改善
  • パスパラメータやクエリパラメータの型定義が可能

2.3 API の変更

  • Remix の API が react-router に統合
  • json() や defer() などの一部 API は削除
  • エントリーポイントのコンポーネントが変更
    • RemixServer → ServerRouter
    • RemixBrowser → HydratedRouter

3. 移行手順

  1. Future Flags の有効化
// vite.config.ts
remix({
  future: {
    v3_fetcherPersist: true,
    v3_relativeSplatPath: true,
    v3_throwAbortReason: true,
    v3_singleFetch: true,
    v3_lazyRouteDiscovery: true,
  },
});
  1. 依存パッケージの更新
  • @remix-run/_ → @react-router/_ に置換
  • codemod を使用して自動更新可能:
npx codemod remix/2/react-router/upgrade
  1. package.json の scripts 更新
- "dev": "remix vite:dev"
+ "dev": "react-router dev"
- "build": "remix vite:build"
+ "build": "react-router build"
  1. routes.ts ファイルの追加
  • コンフィグベースまたはファイルベースのルーティング設定
  1. react-router.config.ts の追加
import type { Config } from "@react-router/dev/config";
export default {
  ssr: true,
} satisfies Config;
  1. Vite プラグインの更新
- import { vitePlugin as remix } from "@remix-run/dev";
+ import { reactRouter } from "@react-router/dev/vite";

export default defineConfig({
  plugins: [
-   remix(),
+   reactRouter(),
  ],
});
  1. 型生成の設定
// tsconfig.json
{
  "include": [
+   ".react-router/types/**/*"
  ],
  "compilerOptions": {
-   "types": ["@remix-run/node", "vite/client"],
+   "types": ["@react-router/node", "vite/client"],
+   "rootDirs": [".", "./.react-router/types"]
  }
}

4. 開発体験の向上

4.1 型安全性の強化

  • 自動型生成

    • ルートパラメータの型が自動生成され、パスパラメータの typo を防止
    • loader や action の戻り値の型が自動的に推論され、コンポーネントでの型エラーを防止
    • クエリパラメータの型安全性も向上
  • loader 関数の型定義の改善

    // Remix v2 での型定義
    export const loader: LoaderFunction = async ({ params }) => {
      const data = await fetchData(params.id); // params.id の型が不明確
      return json(data); // 戻り値の型も不明確
    };
    
    // React Router v7 での型定義
    import type { Route } from "./+types/product";
    
    export async function loader({ params }: Route.LoaderArgs) {
      const data = await fetchData(params.id); // params.id が string型と推論される
      return data; // 戻り値の型が自動的に推論される
    }
    
    // コンポーネントでの型安全な利用
    export default function Product({ loaderData }: Route.ComponentProps) {
      // loaderDataの型が自動的に推論される
      const { name, description } = loaderData;
      return (
        <div>
          <h1>{name}</h1>
          <p>{description}</p>
        </div>
      );
    }
    
    • 関数のオーバーロードサポート
    // 複数の戻り値パターンを型安全に定義
    export async function loader({ params }: Route.LoaderArgs): Promise<Product>;
    export async function loader({ params }: Route.LoaderArgs) {
      if (params.id === "special") {
        return redirect("/special-products");
      }
      const product = await getProduct(params.id);
      return product;
    }
    
    • loader や action で複数の戻り値パターンを型安全に定義可能
    • リダイレクトとデータ返却の両方を扱うケースでも型の整合性を保証

4.2 開発効率の向上

  • コード分割の最適化

    • ルートごとの自動的なコード分割
    • 必要なモジュールのみを効率的にロード
  • データフェッチの改善

    • loader/action の実行結果が自動的に再検証
    • 楽観的 UI の実装が容易に
    • Suspense と組み合わせた効率的なローディング制御

4.3 Web 標準への準拠

  • 標準 API の活用
    • Response/Request API の直接利用
    • Web Streams を使用した SSR の最適化
    • FormData や URLSearchParams の活用

5. 移行の判断基準

移行を推奨するケース:

  • React 19 への対応を予定している
  • 型安全性の向上を求めている
  • フルスタック機能を活用したい

待機を検討するケース:

  • RSC 対応版のリリースを待ちたい
  • 現行の Remix v2 で問題ない
  • 大規模な移行リソースが確保できない

6. まとめ

  • codemod を活用することで比較的スムーズな移行が可能
  • React 19 対応を見据えた場合は移行が推奨
  • 型安全性が向上し、開発体験が改善
  • Remix の機能を継承しつつ、より統合された開発体験を提供
  • Web 標準に準拠した API で、より直感的な開発が可能に
  • 型安全性の強化により、開発時のエラーを早期に発見可能

参考文献

VALLIS, LLC.

Discussion