🐡

Remix でルーティング設定時、 routes のネストを深くしたい

2024/03/07に公開

背景

前提条件

  • Remix ^2.7.2
  • Vite ^5.1.0
  • remix-flat-routes ^0.6.4

初めに

Remix はファイルベースルーティングである。
例えば、以下のフォルダ構成にすると、

app/
├── routes/
│   ├── _index.tsx
│   ├── about.tsx
│   ├── concerts._index.tsx
│   ├── concerts.$city.tsx
│   ├── concerts.trending.tsx
│   └── concerts.tsx
└── root.tsx

以下テーブルのように、良い感じにルーティングを定義してくれる。

URL Matched Route
/ app/routes/_index.tsx
/about app/routes/about.tsx
/concerts app/routes/concerts._index.tsx
/concerts/trending app/routes/concerts.trending.tsx
/concerts/salt-lake-city app/routes/concerts.$city.tsx

問題

上記の定義を見て、個人的にフォルダ構造を深く設定したい欲求が発生した。
機能や関心を単位として、1つのフォルダにファイルを置きたい。
また、 URL のパスが深くなると、 . を繋げていくため、ファイルまたはフォルダ名が長くなる懸念がある。

しかし Remix では、フォルダのネストを深くしても、ルートを作成しないことがわかった。
どうにか解決したい。

app/routes直下のフォルダのみがルートとして登録されます。深くネストされたフォルダは無視されます。app/routes/about/header/route.tsxのファイルはルートを作成しません。

app/
├── routes/
│   └── about/
│       ├── header/
│       │   └── route.tsx
│       └── route.tsx
└── root.tsx

ref: Route Configuration | Remix

選択肢

案1: remix.config.js に手動で定義

手間がかかるし避けたかった。
ファイルベースルーティングなんだから、深いネストもフォルダ構造で良い感じにして欲しい気持ちが強くなる。

Remixではremix.config.jsを使って手動でルートを設定することができます。この柔軟性により、開発者はプロジェクトに適した方法でアプリケーションを構成することができます。
ref: Route Configuration | Remix

案2: remix-flat-route を導入

Remix のリファレンスに remix-flat-routes ってライブラリの紹介があった。
ref: Route File Naming | Remix

解決策: remix-flat-route を導入

ライブラリをインストールする。

yarn add -D remix-flat-routes

Remix + Vite の場合、 remix.config.js ではなく vite.config.ts に定義するため注意すること。
Vite | Remix

import { flatRoutes } from 'remix-flat-routes';
import { vitePlugin as remix } from '@remix-run/dev';
import { defineConfig } from 'vite';
// ...

export default defineConfig({
  plugins: [
    remix({
      ignoredRouteFiles: ['**/*'],
      routes: async (defineRoutes) => flatRoutes('routes', defineRoutes),
    }),
    // ...
  ],
  // ...
});

結果

満足。

なお、結果に記載したフォルダ構造は、TODO リストの CRUD アプリケーションをイメージして記述した。
完成後のリポジトリは以下の通り。
ref: masayuki-0319/remix_todoapp at topics/add_remix_flat_routes

Before

app/routes
├── _index.tsx
├── posts
├── posts.$postId
│   └── route.tsx
├── posts.$postId.delete
│   └── route.tsx
├── posts.$postId_.edit
│   └── route.tsx
├── posts._index
│   └── route.tsx
└── posts.new
    └── route.tsx

After

app/routes
├── _index.tsx
└── posts+
    ├── $postId.delete.tsx
    ├── $postId.edit.tsx
    ├── $postId.tsx
    ├── index.tsx
    └── new.tsx

参考 URL

remix-flat-routes
kiliman/remix-flat-routes: Remix package to define routes using the flat-routes convention

remix-flat-routes 導入リポジトリ
epicweb-dev/epic-stack: This is a Full Stack app starter with the foundational things setup and configured for you to hit the ground running on your next EPIC idea.
kentcdodds/kentcdodds.com: My personal website

remix-flat-routes 紹介
Remix v2 のルーティングにおける flat-routes と Dot Delimiters

Discussion