Waka blog.

Remix -> React Router移行

はじめに

RemixとReact Routerが統合された。本ブログはRemixで構築しているため、React Routerへの移行を行うことにした。

移行ガイド

以下を参考に進める

https://reactrouter.com/upgrading/remix

移行手順

  1. remixのバージョンを最新に上げる

    npm install @remix-run/{dev,react,node,etc.}@2

    自分の環境だと、dev, react, cloudflare, cloudflare-pages

  2. futureフラグを有効化
    1. 下記ガイドを参考に進める

      https://remix.run/docs/en/main/start/future-flags#v3_fetcherpersist

    2. v3_fetcherPersist
      1. フェッチャーの状態をページ遷移後も保持する機能
      2. コードの変更無し
    3. v3_throwAbortReason
      1. エラーハンドリングの改善
      2. コードの変更無し
    4. v3_singleFetch
      1. ネストされたルートのローダーを単一のフェッチにまとめる
      2. vite.config.tsに以下の記述を追記
        declare module "@remix-run/cloudflare" {
          // or node, deno, etc.
          interface Future {
            v3_singleFetch: true;
          }
        }
      3. loaderの戻り値を @remix-run/cloudflare のjsonでラップせず、生のオブジェクトを返す
        1. return json(data) -> return data
    5. v3_routeConfig
      1. react-routerのルーティング方式に変更する
        1. 今回はremix形式引き継ぐので設定しない
    6. 最終的にこんな感じに
      import {
        cloudflareDevProxyVitePlugin,
        vitePlugin as remix,
      } from "@remix-run/dev";
      import { defineConfig } from "vite";
      import tsconfigPaths from "vite-tsconfig-paths";
      
      declare module "@remix-run/cloudflare" {
        // or cloudflare, deno, etc.
        interface Future {
          v3_singleFetch: true;
        }
      }
      
      export default defineConfig({
        plugins: [
          cloudflareDevProxyVitePlugin(),
          remix({
            future: {
              v3_fetcherPersist: true,
              v3_relativeSplatPath: true,
              v3_throwAbortReason: true,
              v3_singleFetch: true,
              v3_lazyRouteDiscovery: true,
            },
          }),
          tsconfigPaths(),
        ],
      });
  3. codemodでremixをreact-routerに置換
    1. npx codemod remix/2/react-router/upgrade
    2. npm install
      1. ここでエラー
        npm ERR! code E404
        npm ERR! 404 Not Found - GET https://registry.npmjs.org/@react-router%2fcloudflare-pages - Not found
        npm ERR! 404 
        npm ERR! 404  '@react-router/cloudflare-pages@^7.0.0' is not in this registry.
        npm ERR! 404 
        npm ERR! 404 Note that you can also install from a
        npm ERR! 404 tarball, folder, http url, or git url.
        
        npm ERR! A complete log of this run can be found in: /Users/wakabayashitoshiyuu/.npm/_logs/2024-12-28T01_53_13_408Z-debug-0.log
    3. package.jsonから @react-router/cloudflare-pages を削除して再度 npm install
  4. プロジェクト内の @react-router/cloudflare-pages importを @react-router/cloudflare に置換
    1. functions/[[path]].ts
      import { createPagesFunctionHandler } from "@react-router/cloudflare";
      import type { ServerBuild } from "react-router";
      
      // eslint-disable-next-line @typescript-eslint/ban-ts-comment
      // @ts-ignore - the server build file is generated by `remix vite:build`
      // eslint-disable-next-line import/no-unresolved
      import * as build from "../build/server";
      
      export const onRequest = createPagesFunctionHandler({
        build: build as unknown as ServerBuild,
      });
  5. package.jsonのscriptsを更新
    1. codemodで更新されていたため、手直し無し
  6. app/route.tsの作成(任意)
    1. react-router的なルーティングを実現したい場合は作成する。従来のremix方式で良いなら作成しない
  7. vite.config.ts修正
    1. remix使用からreact-router使用に置き換え(codemodでは修正されない)
    2. futureフラグは必要ないので削除
    3. cloudflareDevProxyVitePluginをcloudflareDevProxyに変更
      import { reactRouter } from "@react-router/dev/vite";
      import { defineConfig } from "vite";
      import tsconfigPaths from "vite-tsconfig-paths";
      import { cloudflareDevProxy } from "@react-router/dev/vite/cloudflare";
      
      declare module "@react-router/cloudflare" {
        // or cloudflare, deno, etc.
        interface Future {
          v3_singleFetch: true;
        }
      }
      
      export default defineConfig({
        plugins: [cloudflareDevProxy(), reactRouter(), tsconfigPaths()],
      });
  8. 複数の react-router インポートが存在するファイルが出てくるのでまとめる
  9. 従来のファイルベースのルーティングを使用するための設定
    1. @react-router/fs-routes
    2. touch app/routes.ts
    3. 以下の内容を記載
      import { type RouteConfig } from "@react-router/dev/routes";
      import { flatRoutes } from "@react-router/fs-routes";
      
      export default flatRoutes() satisfies RouteConfig;
  10. tsconfig.json 修正
    1. typesの @remix-run/cloudflare -> @react-router/cloudflare
  11. npm run dev で起動確認

以上