💿

RemixでのコロケーションがRoute File Naming(v2)でどのように変わるか

2023/03/07に公開

昨今、Webフロントエンドにおいて「コロケーション」という考え方を見聞きすることがあります。

これは、関連するソースファイルやリソースを近くに置いておく、という考え方で、ソースコードの整理・管理に幅広く適用できます。

最近よく採用される(要出典)SSRフレームワークにおいても例外ではありません。
しかし、この類のフレームワークではファイルシステムベースのルーティングを採用していることが多く、その性質上ひと工夫必要です。

本記事では、まずRemixでコロケーションを実現する方法と注意点について解説します。
次に、新しい命名規則であるRoute File Naming(v2)におけるコロケーションの実現方法と、従来の方法にあった問題点がどのように解決されているかを解説します。

Route File Namingにおけるコロケーションについて

Route File Naming でのコロケーション実現方法

下記のように設定し、 _private ディレクトリ以下のファイルをルートファイルとして扱わないようにします。

remix.config.js
module.exports = {
  ignoredRouteFiles: ["**/.*", "**/_private/**/*"],
};

このようにすることで、例えば下記のようなディレクトリ構造において、 routes/some-feature/_private ディレクトリ以下のファイル群はルートファイルとして認識されないようになります。

/routes
└── some-feature
    ├── index.tsx
    └── _private
        └── internal-component.ts

Route File Naming でのコロケーションの注意点

Route File Namingにおいては、基本的に /routes 以下の js, jsx, ts, tsx ファイルが全てルートファイルだとみなされます。

この場合、Remixでコロケーションをやりたい、という場合に困ってしまいます。
というのも、下記のようなディレクトリ構造があったとして、 internal-component.tsx からsome-feature ディレクトリ内で内部的に使うコンポーネントをデフォルトエクスポートしたい、というケースを考えます。

/routes
└── /some-feature
    ├── index.tsx
    └── internal-component.tsx

そうすると、 internal-component.tsx はルートファイルとして認識され、さらにコンポーネントをデフォルトエクスポートしているので、 /some-feature/internal-component にアクセスするとその内容がレンダリングされてしまうことになります。

よくみるやり方とその問題点

Remixを始めとしたファイルシステムベースのルーティングを採用したSSRフレームワークでよく見るのが、縦割りのディレクトリ構造を使うやり方です。

/components
└── some-feature
    └── internal-component.tsx
/routes
└── /some-feature
    └── index.tsx

この方法だと components/some-featureroutes/some-feature を行ったり来たりすることになったり、内部的に使いたかったコンポーネントを他のモジュールから予期せず再利用されてしまう、といった懸念があったりします。

Route File Naming(v2)について

Route File Naming(v2)は、Remixの新しいルートファイルの命名規則で、設定ファイルで有効化することができます。

remix.config.js
module.exports = {
  future: {
    v2_routeConvention: true,
  },
};

この新しい命名規則では、なんの工夫もなく、より簡単にコロケーションを扱えます。
というのも、RemixのRoute File Naming(v2) では大幅な変更がなされており、

ディレクトリ内に route.tsx あるいは index.tsx があるとき、ディレクトリ内の他のモジュールはルートファイルとして認識されないようになっているからです。

例えば、下記のようなディレクトリ構造があるとき、URLと対応するルートファイルは表のようになります。

/routes
├── posts.$var.tsx
└── posts._index
    ├── route.tsx
    └── util.ts
パス ルートファイル
/posts /routes/posts._index/route.tsx
/posts/123 /routes/posts.$var.tsx

従来の命名規則と互換性はないのですが、とてもシンプルで扱いやすくなったように感じます。

Discussion