React / Next.js / Remixに見られる、この頃のアーキテクチャの変化をキャッチアップすべく、横断的なトピックを紹介する本連載。第3回はここ数年で起きたNext.jsとRemixのルーティングの変化を見ながら、現在のルーティングアーキテクチャについて学んでいきます。
Next.jsとRemixそれぞれのルーティングの変化
昔、Reactを使ったSPA(Single Page Application) はルーティングを以下のように指定していました。これはreact-router-dom
を使った指定の方法です。ここではルーティングのURLセグメントは3つあり「トップページ」と「Companyページ」そしてCompanyの子ページとして「Historyページ」があると仮定します。
react-router-dom
では表示する要素にReactコンポーネントを指定します。element
という属性で指定している箇所です。ここでは「Appコンポーネント」「Companyコンポーネント」「Historyコンポーネント」です。各コンポーネントについて具体的な紹介はしませんが、コーポレートサイトの各ページを表していると思ってください。
const AppRoutes = () => {
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<App />} />
<Route path="/company" element={<Company />} />
<Route path="/company/history" element={<History />} />
</Routes>
</BrowserRouter>
);
};
Next.jsやRemixといったフレームワークでは、ルーティングの機能が搭載されており、ファイルベースルーティングという、実際のディレクトリやファイルの構造がそのままURLのパスになるシンプルな仕組みを採用していました。
「採用していました」と書いたのは、今のバージョンではどちらも以前より複雑なルーティング構築ルールになっているからです。
Next.jsのルーティング
まずは、Next.jsのPage RouterからApp Routerへの変化を見ていくことでNext.jsのルーティングに起きている変化を見ていきます。
■Pages Routerのおさらい
Next.jsは以前はPages Routerというシンプルなファイルベースルーティングでした。例えばこんな感じです。先ほどのreact-router-dom
と同様のルーティング構成を再現してみます。
pages
以下にトップページ、そしてcompany
のトップページがあり、並列階層にhistory
があります。それぞれtsx
ファイルがそのままルーティングの定義になっており、そのままURLのパスになります。index.tsx
は静的なHTMLでいうところのindex.html
に相当します。わかりやすいですよね。
しかし、バージョン13.4からは、App Routerというルーティング方式がデフォルトに変わりました。当時のリリース記事を紹介します。
Next.jsのドキュメントを見ると、現状はまだ古いスタイルのルーティングを利用しているプロジェクトなどもあるため、両方のルーティングスタイルについてのドキュメントが用意されています。
そのため、現状はすでにApp Routerが推奨されていますが、まだPages Routerを使うこともできます。その場合、新規Next.jsプロジェクトを作成する際、以下のように聞かれるので、ここで「No」を選択すると、Pages Routerを使用することができます。
✔ Would you like to use App Router? (recommended) … No / Yes
■App Routerではこうなる
一方、App Routerは少し複雑です。App Routerを使用した場合は前回解説したReact Server Component(RSC)を使うことになります。従って、ページをServer Componentとして定義するか、useState
などのhooksを利用したい場合はClient Componentを使ってコンポーネントを書いていくことになります。
つまりApp Routerを採用するということは、そのあたりのRSC周りのルールも意識する必要があるため、Pages Routerに比べるととっつきにくくなっているのです。
ディレクトリ構成自体は、Pages Routerでいうところのindex.tsx
がpage.tsx
となります。ただし、Pages Routerではhistory.tsx
という名前にすると/company/history
のルーティング定義ができたのに対して、App Routerでは必ずディレクトリを作成した上でpage.tsx
を用意する必要があります。以下のような感じです。
page.tsx
(もしくは.jsx
)は決められたファイル名です。他にもlayout.tsx
という名前にすることによりレイアウトを定義したりerror.tsx
という名前にすることでエラー時の表示を定義できたりします。App Routerのいい点は、各ディレクトリ階層ごとにこれらのファイルを配置することができ、URLのパスに応じたレイアウトなどを容易に定義することができる点です。
あらかじめ定義されたファイル名は以下のドキュメントから確認できます。
またApp Routerではより複雑なルーティング機能としてRoute GroupsやParallel Routes、Intercepting Routesなど多彩なルーティング機能が用意されています。今回は割愛しますが、複雑な要件を解決するのに役立つことでしょう。興味のある方はこちらもチェックしてみてください。
Remixのルーティング
続いてRemixを見ていきましょう。Remixもここ最近大きな変化が起きました。
まず、近い将来RemixはRemixという名前でなくなります。現在Remixはバージョン2系が最新版ですが、次のメジャーアップデートではバージョン3にはならず、RemixはReact Router v7という別の名前でリリースされることになっています。これは単純に名前だけが変わるというだけでなく、現状のRemixにはない機能も搭載される予定です。
ただし、上記の大きな変更もまだ先の話であるため、全く別の展開が待っているかもしれませんが、今後の流れをあらかじめ知っておくといいでしょう。
■Remix v1ルーティングのおさらい
さて、過去1年のRemixを振り返ってみても大きな変更がありました。それら変更のうち、ここではルーティング方式の変化について取り上げます。
Remixはいくつかのルーティング方式を選択できますが、バージョン1では以下のようにディレクトリもしくはファイル名でURLのパスを定義していくスタイルでした。
root.tsxはルートのレイアウトを定義する役割を持ったファイルです。ちなみにバージョン1のドキュメントを見るとわかりますが、上記のシンプルなルーティングのほかにもさまざまな指定の仕方があり、複雑なルーティング定義も行えるつくりになっていました。
■Remix v2ルーティングではこうなった
バージョン2ではどう変わったのでしょうか。バージョン1と同様のルーティング定義をバージョン2向けに書き直すと以下のようになります。
▲Remix v2のルーティングで再定義
まず変わったところとして、app/routes
ディレクトリ以下にはファイルのみになっています。
見たところ、ファイルの構造がそのままファイル名になっているようです。ドットデリミタというスタイルのファイル名規約です。この形式はフラットなフォルダ以下にすべてのルーティング定義が並ぶことになるため、全体を把握しやすいというメリットがあります。バージョン2からはこのような書き方がデフォルトになりました。
_index.tsx
はトップページにあたる名前です。以前であればindex.tsx
が該当します。
この書き方はどうしても受け入れられないという人向けには第1階層目にディレクトリまでのパスを書くスタイルも使えます。こんな具合です。
この書き方ではroutes
以下をドットデリミタでパスを表現したディレクトリ名と、その子としてroute.tsx
という名前のファイルを配置しています。
ちなみに以前のファイルベースルーティングのようにディレクトリを入れ子にしてルーティング定義をすることはできません。Next.jsのApp Routerのようにpage.tsx
を使った構成に少し似ていますね。この形式であれば、ディレクトリ内に他のファイルなどを含めることができます。
Next.jsとRemixのルーティングに関する考え方の違い
Next.jsのApp Routerは、パス単位で必要なファイルをまとめるのに適した構造をしています。仮にルーティングのディレクトリ配下にconfig.ts
のようなファイルを配置したとしても、/config
のようなURLでアクセスされる心配はありません。これはSafe colocation(安全に、使用箇所のなるべく近くに配置する)という機能としてデフォルトで提供されているものです。
またNext.jsのApp Routerは、「ルーティングのわかりやすさ」については、Pages Routerに比べればわかりやすさは減るものの、基本的にはディレクトリ構造にマッチしたURLパスとなるという点では、わかりやすいと、筆者個人としては考えています。ただし、App Routerの高度な機能を使えば使うほどディレクトリ構造は複雑になりわかりにくくなる点には注意が必要です
一方、Remixのv2ルーティングにおいては、今までのディレクトリ単位でURLパスを切るファイルベースルーティングではなく、ドットデリミタによるファイルベースルーティングになったことで、階層構造のわかりやすさは減りました。しかしながら同一階層上にすべてのルーティングを表現できるという点においては一覧性が向上したと言えます。
Next.jsとRemixにおいてはそれぞれベースのルーティングに関する考え方は大きく異なり、それを補完する形で応用的なルーティング定義の方法が用意されているのです。
マイグレーションのサポートが便利
フレームワークを新しいバージョンにアップグレードしていくことをマイグレーションといいます。このマイグレーション作業は、以前は非常に手間でした。フロントエンドにおいては、フレームワークのバージョンアップの間隔が狭いうえに、破壊的変更が起きることもたびたびあったのです。
しかしながら近年は破壊的変更が起きるにしても、ユーザーのマイグレーションの負荷をなるべく減らすように注意が払われています。例えば、先ほどとりあげたNext.jsやRemixではいきなり過去のルーティング方式が使えなくなるということはないように作られています。
以下では、さまざまなマイグレーション周りのサポートを紹介します。
■React Canary
Reactは安定版が出る前に「Canaryリリースチャンネル」を出すという方針が2023年に発表されました。これにより、安定板と同様の新しい機能を事前に試して検証を行うことができるようになりました。
Canaryリリースチャンネルとは別に実験的な機能を含んだ「Experimentalリリースチャンネル」というものもありますが、Canaryリリースチャンネルは、それとは異なり、安定版で採用される状態になった機能が含まれています。
現在Reactを採用しているプロジェクトで新しいバージョンを検証する必要がある場合、新しいバージョンを待たずにCanaryリリースを使うことができます。新しいバージョンの導入を考えはじめたら、まずはこのチャンネルを使って動作確認をするところからはじめると便利でしょう。
■Codemod
Reactは、古いAPIから新しいAPIに変わった際に各ファイルを一つずつ手で修正してもいいですが、Codemodによるマイグレーションもサポートしています。Codemodはオープンソースで開発が進められているコードマイグレーションツールです。Reactではバージョン19RCに移行するためのレシピが公開されています。
レシピを指定すると、どのレシピを実行するかを選ぶことができ、実行することで更新の必要があるかどうかも含めてチェックすることができます。
■RemixのFuture Flags
Remixの機能がこの1年で大きく変わったことについては前述した通りですが、将来はどうでしょうか。近い将来フレームワークの名前ごと変わる可能性が示唆されていますが、こんな風にどんどん変わっていってしまったら導入する側は大変です。
Remixでは、「段階的な機能の採用」を掲げており、それによってユーザーはシームレスなバージョンのアップグレードが可能になるとしています。
それを実現するための一つがFuture Flagsです。今までのバージョンアップではバージョン3になると全てのバージョン3の機能が有効になり、急な対応を求められるといったことが多かったと思いますが、Remixではバージョン3にて提供される機能単位でv3_
というプレフィクスをつけた機能フラグが用意されます。例えば新しくRemixプロジェクトを作成した場合、以下のようにv3_
プレフィクスがついたFuture Flagsが有効化されています。
vite.config.ts
export default defineConfig({
plugins: [
remix({
future: {
v3_fetcherPersist: true,
v3_relativeSplatPath: true,
v3_throwAbortReason: true,
},
}),
tsconfigPaths(),
],
});
先行き不確かな未来ですが、いつバージョンアップが起きてもいいように、マイグレーション方法について把握し、スムーズなアップグレードを心がけたいところです。
・・・
いかがでしたか。全3回にわたって、Webフロントエンド技術の最前線を見てきました。盛りだくさんだったので、少し難しく感じる部分もあったかもしれません。ですが、まずは気になったキーワードを調べるところからはじめて、仕様書などを丁寧に読んでいくことで、確実に力をつけていくことができます。これからもフロントエンドの世界は果てしなく広がっていきます。一緒に探求を進めていきましょう。
▼React / Next.js / Remix にみるこの頃のアーキテクチャ変化
1:React 19 のアップデートにみる変化
2:レンダリングアーキテクチャの変化
3:フロントエンドルーティング定義の変化