【typoとおさらば】AppRouterで画面URL定義の自動生成をしてくれるpathpida
pathpida
を利用して画面のURL定義を自動生成するのは、めちゃくちゃ便利です!
自動生成を一度経験してしまったら、もう手作業で画面URLの定義を用意していた頃には戻れませんよ…
利用者想定
Next.jsのAppRouterを利用して開発を行っている方
[前提]AppRouterとは
pathpidaを説明する上でAppRouterの前提知識が必要になるので、AppRouterのルーティングについて触れますが、有識者の方は読み飛ばして頂いて構いません。
- ルーティングの特徴
- app配下でpage.tsxファイルが配置されているディレクトリのパスが、そのまま画面のパス(URL)として認識される
pathpida とは?
pathpida は、TypeScript/JavaScript のコード内でルートを型安全に扱うためのユーティリティライブラリです。
AppRouterのルーティングを読み取り、画面URLの定義を自動で生成してくれます。
- 特徴
- 型安全なルート定義
- 定義したルート情報に基づいて、コンパイル時に誤ったルートの利用を検出できるため、実行時エラーを未然に防げます。
- ルートの自動生成サポート
- プロジェクト内のディレクトリ構造から、画面URLの定義を自動的に生成できるため、手動でURLを管理する手間が省け、メンテナンス性が向上します。
- 型安全なルート定義
メリット
pathpida
を用いることで、以下のメリットが得られます。
- 開発効率の向上:コマンド実行のみで画面URLの定義を作成(更新)を行うので、実装者が画面URLの管理をするコストを抑えることができます。
- 型安全性:ルートのミスやタイプミスを防止できます。
- メンテナンス性:ルートの追加・変更が容易になり、コードの一貫性を保てます。
[体験談]なぜルートの自動生成が嬉しいのか?
前述したようにAppRouterは、page.tsxファイルを配置しているディレクトリのパスがそのまま画面のURLになります。
一見、画面のURLがわかりやすくなると思いますが、、、
AppRouter独自の命名規則でディレクトリを分けたり、app配下にルーティングに関係しないcomponentsやhooksディレクトリを作成すると、どのディレクトリが画面のURLとして扱われるのかが分かりにくくなってしまいます。
(実際のディレクトリです。どれが画面のURLとして扱われるのかパッとはわからないですね。。)
しかし、pathpidaを導入したおかげで、画面URLが自動で生成されるようになり、自分で管理する必要がなくなったため、上記の問題は解決しました✨
またpathpida
が生成した定義を利用するので、画面URLのtypoの心配もなくなります!
pathpida導入
- まずは、
pathpida
をinstall
bun add pathpida npm-run-all --dev
- scripts設定
{
"scripts": {
...,
"dev:path": "pathpida --ignorePath .gitignore --watch",
}
}
- コマンドを実行
bun dev:path
$path.ts
ファイルが作成されて、画面のルートが定義されます。
既に$path.ts
ファイルが作成済みの場合は、最新のルート情報に更新されます。
- 使用例
import Link from "next/link";
import { pagesPath } from "../lib/$path";
console.log(pagesPath.post.create.$url()); // { pathname: '/post/create' }
console.log(pagesPath.post._pid(1).$url()); // { pathname: '/post/[pid]', query: { pid: 1 }}
console.log(pagesPath.post._slug(["a", "b", "c"]).$url()); // { pathname: '/post//[...slug]', query: { slug: ['a', 'b', 'c'] }}
export default () => {
const onClick = useCallback(() => {
router.push(pagesPath.post._pid(1).$url());
}, []);
return (
<>
<Link href={pagesPath.post._slug(["a", "b", "c"]).$url()} />
<div onClick={onClick} />
</>
);
};
使用できる関数
pathpidaで定義された関数では、以下の関数を利用できます。
-
.pathname
- URL の「パス部分」を返す
- 「パス部分」とはドメイン直下から始まる静的なパスを指す(ex. /bucket_memo/edit)
-
.query
- URL の「クエリパラメータ」情報を返す
-
.hash
- URL の「ハッシュ部分」、つまり # 以降のフラグメントを返す
-
.path
- 上記の pathname、query、hash を組み合わせた「完全なパス文字列」を返す
// 静的ルーティングの場合
console.log(pagesPath.post.$url().pathname) // "/post"
console.log(pagesPath.post.$url().hash) // "sample" (ハッシュ指定の文字)
console.log(pagesPath.post.$url().path) // "/post/#sample"
// 動的ルーティングの場合
console.log(pagesPath.post._pid(1).$url().pathname) // '/post/[pid]'
console.log(pagesPath.post._pid(1).$url().query) // { pid: 1 }
[体験談]Next.jsのLinkコンポーネントでpathpidaが使えない!?
Linkコンポーネントのhref 属性にpathpidaで定義したURLをセットしようとしたら下記のエラーが発生しました。
// 実装
<Link href={pagesPath.memo.edit._slug(id).$url()} >
内容を編集
</Link>
// エラー
Handling "Dynamic href is not Supported in the App Router" Error in Next.js
参照)https://nextjs.org/docs/messages/app-dir-dynamic-href
Next.jsのLinkコンポーネントの href 属性に動的なパスが使われていると下記のエラーが出る場合があります。
そしてこのエラーは、$url()
メソッドでhref属性に渡すとURLオブジェクトをそのまま返すことになり、その内部でまだプレースホルダーの状態([slug])になっている場合があるために発生するエラーです。
こちらのエラーを解消するためには、「path」関数で静的なパスを渡してあげたらエラーが解決します。
<Link href={pagesPath.memo.edit._slug(id).$url().path} >
内容を編集
</Link>
おまけ
pathpida
の派生元として、aspida
という HTTP クライアントライブラリがあります。
aspida はディレクトリ構造に基づいて API のエンドポイントを自動生成してくれるため、とても便利です。
自社の業務でaspida
を採用しているPJがあったので、そこでこのライブラリの存在を知りました。
まとめ
今回の記事では、pathpida と AppRouter を組み合わせたルート自動生成の手法をご紹介しました。
この組み合わせにより、以下のメリットが得られます。
- ルート定義の型安全性を確保
- 自動生成による開発効率の向上
- 保守性の高いルーティング設定の実現
pathpidaを実際に利用する中で「すごく便利だなぁ」と思ったのでご紹介させていただきました。
Discussion