🦔

【typoとおさらば】AppRouterで画面URL定義の自動生成をしてくれるpathpida

2025/02/20に公開

pathpidaを利用して画面のURL定義を自動生成するのは、めちゃくちゃ便利です!
自動生成を一度経験してしまったら、もう手作業で画面URLの定義を用意していた頃には戻れませんよ…

利用者想定

Next.jsのAppRouterを利用して開発を行っている方

[前提]AppRouterとは

pathpidaを説明する上でAppRouterの前提知識が必要になるので、AppRouterのルーティングについて触れますが、有識者の方は読み飛ばして頂いて構いません。

  • ルーティングの特徴
    • app配下でpage.tsxファイルが配置されているディレクトリのパスが、そのまま画面のパス(URL)として認識される

https://nextjs.org/docs/app/getting-started/project-structure#app-routing-conventions

pathpida とは?

https://github.com/aspida/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導入

  1. まずは、pathpida をinstall
bun add pathpida npm-run-all --dev
  1. scripts設定
package.json
{
  "scripts": {
    ...,
    "dev:path": "pathpida --ignorePath .gitignore --watch",
  }
}
  1. コマンドを実行
bun dev:path

$path.tsファイルが作成されて、画面のルートが定義されます。
既に$path.tsファイルが作成済みの場合は、最新のルート情報に更新されます。

  1. 使用例
component.tsx
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があったので、そこでこのライブラリの存在を知りました。

https://github.com/aspida/aspida

まとめ

今回の記事では、pathpida と AppRouter を組み合わせたルート自動生成の手法をご紹介しました。
この組み合わせにより、以下のメリットが得られます。

  • ルート定義の型安全性を確保
  • 自動生成による開発効率の向上
  • 保守性の高いルーティング設定の実現

pathpidaを実際に利用する中で「すごく便利だなぁ」と思ったのでご紹介させていただきました。

Discussion