>_tech-draft
Vercelのアイコン
Vercel
動画公開日
タイトル

Type-safe URL state in Next.js with nuqs

再生時間

25分 9秒

Next.jsでURLステートを型安全に管理!Nuxが解決する課題とディープリンク活用術

ポイント

  • Next.jsアプリケーションにおけるURLステート(検索パラメーター)管理の重要性と、ディープリンクやタイムトラベルといった「超能力」について解説します。
  • URLステートが抱えるサイズ制限、アプリケーション進化への対応、ブラウザのレート制限、SEOなどの課題を深掘りします。
  • 型安全な状態管理ライブラリNuxがこれらの課題を解決し、開発体験を向上させる仕組みと具体的な活用術がわかります。

Next.jsでURLステートを型安全に管理!Nuxが解決する課題とディープリンク活用術URLの活用はウェブアプリケーションのUXとSEOを大きく左右します。特にNext.jsのようなモダンなフレームワークでは、URLの検索パラメーター(クエリ文字列)にアプリケーションの状態(ステート)を保存する「URLステート」の管理が重要となります。しかし、その実践には多くの課題が伴います。本記事では、Next.jsアプリケーションにおけるURLステートの重要性、その利点と潜在的な問題点、そして型安全なURLステート管理ライブラリ「Nux」がいかにこれらの課題を解決し、開発体験を向上させるかについて詳しく解説します。## Nuxとは?Next.js Confにて紹介されたNuxは、Reactアプリケーション向けの型安全な検索パラメーター状態マネージャーです。現在ではSentry、Superbase、Vercelなど世界中の企業で利用され、週に約100万回ダウンロードされるオープンソースプロジェクトに成長しました。Nuxは、ReactにおけるURLステートの扱いを快適にし、開発者が直面する多くの問題を解決することを目指しています。## URLステートとは何か?URLステートとは、アプリケーションの状態の一部をURLの検索パラメーター、つまりクエリ文字列(URLの「?」以降のキーバリューストア)に保存するという考え方です。これにより、URL自体がアプリケーションの状態を表現する役割を果たします。### URLステートを使用する「誤った」理由ページをリロードしたときに状態の更新を失いたくないという理由は、URLステートを使用する誤った理由です。リロード時の状態保持は、ローカルストレージなどの他の手段でも実現できる副次的な効果に過ぎません。URLに状態を置く真の理由は、アプリケーションに特定の「超能力」を与えることにあります。### URLステートがアプリケーションにもたらす二つの超能力URLに状態を置く本当の理由は、アプリケーションに二つの強力な機能を与えるからです。1. **テレポーテーション(ディープリンク)**リンクを共有することで、あなたのブラウザに表示されている状態のメモリ表現を相手のブラウザと共有し、相手もあなたと同じ画面を見ることができます。これは、あなたが中断した場所から再開できることを意味し、「ディープリンク」と呼ばれます。これにより、特定のフィルターが適用された検索結果や、カスタマイズされたビューなどを簡単に共有できるようになります。2. タイムトラベルブックマークは、未来の自分にリンクを送る方法であり、ブラウザの履歴は過去の状態を呼び戻す方法です。ブラウザの「戻る」「進む」ボタンを使うことで、まるでUndo/Redo機能のように状態をタイムトラベルしてデバッグすることも可能です。これにより、ユーザーはアプリケーションの過去の状態に簡単に戻ることができ、より柔軟な操作が可能になります。ただし、実装方法によってはブラウザの「戻る」ボタンの挙動を壊してしまう可能性があるので注意が必要です。## クライアントとサーバー間の双方向通信としてのURLURLは、クライアントとサーバー間の境界線として機能します。クライアントは現在のドキュメントのURLに状態を添付でき、サーバーはその情報をデータ取得、フィルタリング、カスタムコンテンツの返却などに利用できます。これはウェブの基本的な動作であり、これまでも行われてきました。しかし、現代のウェブアプリケーションでは、クライアントがURLの変更に反応できるようになりました。これにより、サーバーはリダイレクトを使ってクライアントに「ここへ移動し、クライアント側で取得する状態を添付する」と指示することで、同じシステムを利用して返信できます。このように、APIエンドポイントやリクエスト/レスポンスボディを使用せず、URLテキスト自体のみを使用してクライアントとサーバー間の双方向通信リンクを確立できるのは非常に強力です。## URLステートの「氷山の一角」問題URLステートには多くのメリットがある一方で、いくつか注意すべき潜在的な課題も存在します。優れたエンジニアであるためには、これらのシステムの限界を理解することが重要です。### 1. URLのサイズ制限URLにはサイズ制限があります。サーバー側がボトルネックになることは稀ですが、リンクを共有する際のプラットフォームが問題となることがあります。例えば、SignalやWhatsAppでは長いリンクはクリック可能な形式で表示されなかったり、一部のプラットフォームではメッセージが送信されなかったり、リンクが途中で切れてしまったりする可能性があります。しかし、最大の問題は技術的なものではなく、社会的なものです。人間は長いリンクを好みません。例えば、同じ意味を持つ二つのリンクがあった場合、URLエンコードされたJSONやBase64を含む長いリンクよりも、短く人間が理解できるリンクの方がクリックされやすい傾向にあります。URLは、ユーザーがクリックする前に最初に目にするUIの一部であるため、Open Graph画像と同じくらい注意深く設計する必要があります。### 2. URLの不変性 vs アプリケーションの進化ユーザーが共有したリンクは、アプリケーションの視点からは「不変」です。しかし、アプリケーション自体は時間とともに進化し、検索パラメーターのスキーマに破壊的な変更が導入されることがあります。Tim Berners-Leeの「クールなURIは変わらない」という言葉にあるように、過去に共有されたリンクのセマンティクスは可能な限り尊重すべきです。これは、データベースにおけるスキーママイグレーションと同様の方法で対処できます。Next.js 16以降のミドルウェア(旧プロキシ)を利用し、URLから受け取った状態を、キーの名前変更やデータ型の変更などによって、アプリケーションが期待する現在の状態に変換(マッサージ)し、リダイレクトを通じてアプリケーションに渡すことで解決できます。### 3. ブラウザによるURL更新のレート制限ブラウザはセキュリティ上の理由から、クライアントサイドからのURL更新にレート制限を設けています。この挙動はブラウザによって異なり、FirefoxやChromeは比較的寛容ですが、Safariははるかに厳しい制限があります。例えば、検索入力フィールドにキーが押されるたびにURLを更新するような実装を行うと、Safariでは約10秒でアプリケーションがクラッシュする可能性があります。Nuxはこの問題に対して、組み込みの「スロットルキュー」で対応しています。これは「タイムセーフティ」と呼ばれるシステムの一部であり、UIの更新とURLの更新を分離し、ブラウザが処理できるレートでURLの更新をスロットリングします。これにより、URLの更新頻度を制御しつつ、UIには瞬時に楽観的な状態更新を提供することで、応答性を維持し、INP(Interaction to Next Paint)のような指標を改善します。### 4. エントリポイントとしてのURLURLに状態を追加すると、アプリケーションへのエントリポイントが作成されます。ブラウザのURLバーは信頼できない入力源であるため、アプリケーションに入力されるデータが安全であることを検証する必要があります。また、URLにプライベートデータを含めないように、出力されるデータにも注意が必要です。エントリポイントの主な問題は、アプリケーションロジックへのバイパスを作成することです。通常ユーザーがクリック操作を経てたどり着くはずの場所へ、リンクを通じて直接アクセスできるようになります。そのため、アプリケーションの状態管理ロジックはこれを考慮に入れる必要があります。### 5. SEO(検索エンジン最適化)SEOに関しては、重要なポイントがあります。重複コンテンツの問題を避けるため、検索エンジンのクローラーがインデックスすべきURLの正規表現(Canonical URL)を設定する必要があります。検索パラメーターを含んだURLであっても、YouTubeの動画IDのように特定のパラメーターはインデックスの対象とすることができますが、それ以外の追跡用や一時的なパラメーターはインデックスから除外すべきです。適切にCanonical URLを設定することで、URLステートを活用しつつSEO上の問題を回避できます。## なぜNuxが必要なのか?Next.jsのApp RouterにはuseSearchParamsフックがあり、すべての検索パラメーターを一度に文字列として取得できます。しかし、これが問題の始まりです。私たちのアプリケーションは文字列以外のデータ型、例えば数値、日付、ブーリアン、オブジェクトなどを必要とします。また、これらのデータ型と特定のキーとの間に強い関連性、つまり型安全なスキーマが必要です。useSearchParamsだけではこれらを自力で処理する必要があり、型変換やバリデーションのロジックが複雑化し、エラーが発生しやすくなります。Nuxはこれらの問題を解決するために設計されています。型安全なスキーマ定義を通じて、検索パラメーターをアプリケーションが必要とする適切なデータ型で利用できるようにし、開発者がURLステートの管理に煩わされることなく、アプリケーションのビジネスロジックに集中できる環境を提供します。## まとめNext.jsアプリケーションにおいてURLステートは、ディープリンクやタイムトラベルといった強力な機能を提供し、ユーザー体験を大きく向上させる可能性を秘めています。しかし、URLのサイズ制限、スキーマの変更、ブラウザのレート制限、セキュリティ、そしてSEOといった多くの課題を伴うことも事実です。Nuxは、これらの複雑なURLステート管理の課題に対し、型安全なアプローチと組み込みの機能を提供することで、開発者がより快適かつ堅牢にURLステートを扱えるようにサポートします。Next.jsアプリケーションでURLステートのパワーを最大限に引き出しつつ、その落とし穴を回避するために、Nuxの導入を検討してみてはいかがでしょうか。## 参考動画Next.js Conf 2023 - Building a type-safe URL state manager with Nux