2024/11追記
React Router v7 を使いましょう
追記終わり
React Router と Vite の環境で、Remix ライクなファイルベースルーティングシステムを実装してみた。
https://github.com/isoden/react-router-file-based-routing
React Router でファイルベースルーティングを実現する仕組み自体は新しいものではない。有名なところだと https://github.com/oedotme/generouted がある。
既存のものと違うのは、 Remix の Route File Naming をサポートしている点。
README にも書いたが、以下のディレクトリ構造があると、次の routes オブジェクトが生成される。
src/routes
├── 404.tsx
├── _auth.login.tsx
├── _auth.register.tsx
├── _auth.tsx
├── _index.tsx
├── _root.tsx
├── app
│ └── route.tsx
├── app._index
│ └── route.tsx
├── app.projects
│ └── route.tsx
├── app_.projects.$id.roadmap
│ └── route.tsx
├── concerts.$city.tsx
├── concerts._index.tsx
├── concerts.trending.tsx
├── concerts.tsx
├── concerts_.mine.tsx
├── files.$.tsx
├── optional.($lang).$productId.tsx
└── optional.($lang).categories.tsx const routes: RouteObject[] = [
{
/* Component: import('src/routes/_root') */
children: [
{
index: true,
/* lazy: import('src/routes/_index') */
},
{
/* lazy: import('src/routes/_auth') */
children: [
{
path: 'login',
/* lazy: import('src/routes/_auth.login') */
},
{
path: 'register',
/* lazy: import('src/routes/_auth.register') */
},
],
},
{
path: 'app',
/* lazy: import('src/routes/app/route') */
children: [
{
index: true,
/* lazy: import('src/routes/app._index/route') */
},
{
path: 'projects',
/* lazy: import('src/routes/app.projects/route') */
},
],
},
{
path: 'app/projects/:id/roadmap',
/* lazy: import('src/routes/app_.projects.$id.roadmap/route') */
},
{
path: 'concerts',
/* lazy: import('src/routes/concerts') */
children: [
{
index: true,
/* lazy: import('src/routes/concerts._index') */
},
{
path: 'trending',
/* lazy: import('src/routes/concerts.trending') */
},
{
path: ':city',
/* lazy: import('src/routes/concerts.$city') */
},
],
},
{
path: 'concerts/mine',
/* lazy: import('src/routes/concerts_.mine') */
},
{
path: 'files/*',
/* lazy: import('src/routes/files.$') */
},
{
path: 'optional',
children: [
{
path: 'lang?',
children: [
{
path: 'categories',
/* lazy: import('src/routes/optional.($lang).categories') */
},
{
path: ':productId',
/* lazy: import('src/routes/optional.($lang).$productId') */
},
],
},
],
},
{
path: '*',
/* Component: import('src/routes/404') */
},
],
},
] なぜこれを書いたか。Create React App 時代から開発・保守を続けているプロジェクトがあって、そこにファイルベースルーティングを導入したかったからだ(バンドラー自体は Vite に移行済み)。
今から新規に SPA を作るなら Remix の SPA mode も選択肢に上がると思うが、そう簡単にフレームワークを導入(または移行)できないプロジェクトも多いだろう。
WIP
No comments yet