Slide 1

Slide 1 text

Nuxt × Vue Router の力を Nuxt × Vue Router の力を 最大限に引き出す機能を紹介 最大限に引き出す機能を紹介 Yutaro Koizumi 2024-10-19 @ Vue Fes Japan 2024

Slide 2

Slide 2 text

自己紹介:Yutaro Koizumi (Twitter:@ykoizumi0903) 所属:株式会社アンドパッド(ANDPAD) 工事現場の見積・予算などを作成・確認する「原価管理」 (Nuxt) 承認フローを一元管理する「資料承認」 (Nuxt / Next.js 併用)などを担当 ※興味のある方はぜひスポンサーブースまでお越しください Zenn や ANDPAD TECH BLOG で記事を書いています 以下は個人的に気に入っているオススメ記事です 祝・正式リリース!5つのテーマで理解する Nuxt3 の魅力 UnJS にどんなツールがあるのか、上位30件すべて紹介してみた(前編) 新規プロダクトの開発に Nuxt 3 を採用して良かったこと Writable Computed を活用して読みやすいVueコードを書くためのTips Vue Fes Japan 2024 開催直前! ykoizumi0903 が語る Vue 推しの理由

Slide 3

Slide 3 text

前置き:このテーマを選んだ理由 Nuxt のルーティング周りのキャッチアップは意外と難しい Nuxt と Vue Router の管理が違うので、片方のドキュメントを読んでも全ての情報が掴めない Vue におけるメタフレームワークの比較対象が少ないので、注目されにくい React の場合、Next.js、Remix、Astro、Gatsby それぞれの特徴を比べられる Vue 2 の頃からある機能も多く、「Vue 3・Nuxt 3 の新機能」ではないので、紹介される機会が少ない => Nuxt × Vue Router でできることをさわりだけでも紹介することで、   「そういえばこれもできたような…」と頭の片隅に置いておいてもらいたい

Slide 4

Slide 4 text

Contents 1. Dynamic Routes 2. Catch-All Route 3. Route Groups (v3.13~) 4. Nested Routes 5. Typed Pages (v3.5~) 6. Routes’ Matching Syntax 7. Path Ranker (Vue Router Path Parser) ※Route Group 以外は Nuxt ではない Vue Router 単体でも使える機能ですが、 説明を簡略化するため、Nuxt 3 での利用を前提として説明します

Slide 5

Slide 5 text

Dynamic Routes pages 内のファイル名やディレクトリ名を [] で囲むことで、動的なルートを作成できる https://nuxt.com/docs/guide/directory-structure/pages#dynamic-routes /users/[user_id]/posts/[post_id].vue のように書くことで、ブラケット部分が任意の文字列にマ ッチする ファイル名の一部のみをブラケットで囲むことで、部分的に動的なルートになる /pages/user-[id].vue など [[]] と二重に囲むことで、そのパスが省略可能になる /user/[[id]].vue は、 /user/ と /user/1 の両方にマッチする

Slide 6

Slide 6 text

Catch-All Route [...id].vue という命名で、スラッシュで区切られた配下のパスに全てマッチする https://nuxt.com/docs/guide/directory-structure/pages#catch-all-route 例: /date/[...dates].vue は、 /date/2024/ と /date/2024/10/ と /date/2024/10/19/ に全 てマッチする $route.params.dates は string[] 型の配列として複数のパスにアクセスできる

Slide 7

Slide 7 text

Route Groups (v3.13~) ディレクトリ名を () で囲むことで、URLに含まれないセグメントを作成できる https://nuxt.com/docs/guide/directory-structure/pages#route-groups /pages/(backstage)/dashboard.vue が /dashboard/ にマッチする (丸括弧内はURL上は無視される) pages ディレクトリを綺麗に整理できる 理論上は同じルートに一致するページコンポーネントを無数に作れてしまうが、避けた方が良い -| pages/ ---| (backstage)/ -----| dashboard.vue ---| (portal)/ -----| login.vue

Slide 8

Slide 8 text

Nested Routes ディレクトリと同じ名前の Vue ファイルを作成することで、ページコンポーネントを多重化できる https://nuxt.com/docs/guide/directory-structure/pages#nested-routes 共通部分の layout、ページごとの pages の二層だけでな く、URLのパスに一致させる形で多層化できる 動的ルートと組み合わせることも可能(ファイル名とディ レクトリ名をブラケット付きで揃える) Route Groups とは組み合わせられない Tips: ページコンポーネント内で子ページを表示する位置は ではなく タグで指定します -| pages/ ---| index.vue ---| red.vue ---| red/ -----| blue.vue -----| blue/ -------| green.vue

Slide 9

Slide 9 text

ちなみに…… ここまで紹介した機能(Dynamic Routes, Catch-All Route, Route Groups, Nested Routes)は、 React フレームワークである Next.js や Remix もほぼ同様の機能を備えている → 実践的な使い方・考え方については Next.js や Remix のドキュメントや記事を参考にするのもオススメで す Routing: Dynamic Routes | Next.js Routing: Route Groups | Next.js Route Configuration | Remix 例:Next.js 公式ドキュメントによる Nested Routes 概念のわかりやすい図

Slide 10

Slide 10 text

Typed Pages (v3.5~) Vue Router のページ遷移や動的パラメータの型情報を取得する https://nuxt.com/blog/v3-5#fully-typed-pages や useRouter().push('path') などで遷移先を指定する際に、存在する パスを補完してくれる 存在しないページを指定するとタイプエラーになる 動的パスの場合も部分的な補完を受けられる(下画像の :filter() の部分)

Slide 11

Slide 11 text

Typed Pages (v3.5~) Vue Router のページ遷移や動的パラメータの型情報を取得する https://nuxt.com/blog/v3-5#fully-typed-pages useRoute() の場合は引数にパスを指定することで、動的パラメータなどの型情報を取得できる 例: /pages/[user_id]/posts/[post_id].vue というページコンポーネントの場合 useRoute('user_id-posts-post_id') と引数を指定することで、paramsでは user_id と post_id のみにアクセスできる useRoute() は自動で推論されないので、自分で適切なコンテキストを与える必要がある composable や components など、ページコンポーネント外で使っている場合は、あえて引数を渡 さないことで型エラーを回避できる

Slide 12

Slide 12 text

Typed Pages (v3.5~) Vue Router のページ遷移や動的パラメータの型情報を取得する https://nuxt.com/blog/v3-5#fully-typed-pages Nuxt Config で設定しないと有効化されない Nuxt 3.5 以上が必要 Nuxt 以外で利用する場合は → posva/unplugin-vue-router 関連記事: export default defineNuxtConfig({ experimental: { typedPages: true } })

Slide 13

Slide 13 text

Routes’ Matching Syntax ファイルベースルーティングでは表現しきれない、より柔軟なルーティングを実現する https://nuxt.com/docs/api/utils/define-page-meta#using-a-custom-regular-expression ここまで紹介した機能で実現できないルーティングを無理やり実現するための機能 動的ルートを特定の文字列のみに制限したり、複数のページパスを同じルートにマッチさせたり /users/:user_id(\\d+) のように書くと、user_id が数字の場合のみマッチする ルートの書き方に Nuxt とは別のルールがある 例えば、動的パスはブラケットではなくコロンを使うなど https://router.vuejs.org/guide/essentials/route-matching-syntax.html を参照

Slide 14

Slide 14 text

Routes’ Matching Syntax ファイルベースルーティングでは表現しきれない、より柔軟なルーティングを実現する https://nuxt.com/docs/api/utils/define-page-meta#using-a-custom-regular-expression 使い方①ページコンポーネントに definePageMeta() を記述する postId が数字である場合のみマッチする /1-new/ にはマッチするが、 /id-new/ にはマッチしなくなる path を上書きするので、ファイル名に基づくルーティングは無視される ファイル名やディレクトリが無関係な場所にあっても関係ない ただし、Nested Routes の影響は受ける 上記のファイルを /pages/red/blue/[postId]-[postSlug].vue に配置した時に、 /pages/red.vue や /pages/red/blue.vue が存在すればネストされたルートとして認識される 影響を受けたくなければ別の場所に移動すれば良いだけなので、便利な場面の方が多いと思います // pages/[postId]-[postSlug].vue definePageMeta({ path: '/:postId(\\d+)-:postSlug' })

Slide 15

Slide 15 text

Routes’ Matching Syntax ファイルベースルーティングでは表現しきれない、より柔軟なルーティングを実現する https://nuxt.com/docs/api/utils/define-page-meta#using-a-custom-regular-expression 使い方② nuxt.config.ts の pages:extend hook を使う definePageMeta() と異なりルートを追加しているので、ファイル名に基づく元のルートも有効 上記の例であれば、 /1-new/ と /red/blue/id-new/ の両方にマッチする pages/ 以外に置いたファイルにマッチさせたり、複数のパスを同じページにマッチさせたりできる さらに素の Vue Router に近い設定方法なので、Vue Router 公式ドキュメントが参考になります export default defineNuxtConfig({ hooks: { 'pages:extend'(routes) { routes.push({ path: '/:postId(\\d+)-:postSlug' file: '~/pages/red/blue/[postId]-[postSlug].vue', }) } } })

Slide 16

Slide 16 text

Routes’ Matching Syntax ファイルベースルーティングでは表現しきれない、より柔軟なルーティングを実現する https://nuxt.com/docs/api/utils/define-page-meta#using-a-custom-regular-expression Typed Pages との組み合わせも可能 definePageMeta() で指定した動的パラメータも正しく型推論・補完される(string 型) useRoute() に渡す引数は、 definePageMeta() ではファイル名、 pages:extend では path 文字列 がデフォルトで使われる(こちらも自動で推論されます) name プロパティを指定すると、好きな名前に上書きすることもできる

Slide 17

Slide 17 text

Path Ranker (Vue Router Path Parser) ルーティングにどのパスがマッチするかを検証する公式ツール https://paths.esm.dev/ 設定しているパスの正規表現と、実際のURLを渡すことでどのページにマッチするかを検証できます パスの優先度をスコアで表示してくれるので、どのパスにマッチするかが一目でわかります

Slide 18

Slide 18 text

Path Ranker (Vue Router Path Parser) ルーティングにどのパスがマッチするかを検証する公式ツール https://paths.esm.dev/ pages/ ディレクトリ内に配置している、自分で正規表現を書いていないパスは? Nuxt が内部で正規表現に変換している どう変換されているかは /.nuxt/types/typed-router.d.ts を開くと確認できる( typedPages を有効にしている場合のみ) /** * Route name map generated by unplugin-vue-router */ export interface RouteNamedMap { 'index': RouteRecordInfo<'index', '/:page_route(page)?/:page(d+)?/', { page_route?: ParamValueZeroOrOne, page?: P 'category-slug': RouteRecordInfo<'category-slug', '/category/:slug/page/:page(\d+)', { slug: ParamValue, page: Pa 'date-dates': RouteRecordInfo<'date-dates', '/date/:dates(.*)*', { dates?: ParamValueZeroOrMore }, { dates?: Para 'red': RouteRecordInfo<'red', '/red', Record, Record>, 'red-blue': RouteRecordInfo<'red-blue', '/red/blue', Record, Record>, 'my-favorite-name': RouteRecordInfo<'my-favorite-name', '/:postId(\d+)-:postSlug()?', { postId: ParamValue, postS 'red-blue-green': RouteRecordInfo<'red-blue-green', '/red/blue/green', Record, Record>, }

Slide 19

Slide 19 text

まとめ Vue Router と Nuxt のルーティングは、標準機能だけで細かいところまでカバーしている強力なツールで す 今回紹介した以外にも、様々な機能や利用例があるので、ぜひ目を通してみてください pages/ · Nuxt Directory Structure Getting Started | Vue Router posva/unplugin-vue-router: Next Generation file based typed routing for Vue Router 実際に触ってみた方がわかりやすいので、まずは試してみるのがオススメです 迷ったら typedPages は有効にしましょう! とりあえずオンにすれば恩恵を受けられる機会は多いと思います

Slide 20

Slide 20 text

ご清聴ありがとうございました!