こちらは Hubble Advent Calendar 2025 の19日目の記事です。
はじめに
株式会社Hubbleのフロントエンドを担当している @moneyan9 です。
Angularのルーティングにおいて canMatch と canActivate は頻繁に利用するガードです。
使い分けは理解しているつもりでしたが、複雑なガードになると「どちらを使うべきか」で迷うことがあります。
その理由は、どちらのガードでも実装できてしまうケースがあるためです。
本記事では canMatch / canActivate の使い分け基準を整理してみて、実際のプロジェクトではどのように使われていたのかを評価してみました。
canMatch と canActivate の違い
まずは基本に立ち返って canMatch と canActivate の違いを整理してみます。
| 項目 | canMatch |
canActivate |
|---|---|---|
| 判定内容 | ルートを候補に含めるか | ルートに遷移してよいか |
| タイミング | ルートマッチング前 | ルートマッチング後 |
| ルートパラメータ | 使えない | 使える |
false を返す |
次のルートを試行 | ナビゲーションを停止 |
UrlTree を返す |
指定先へリダイレクト | 指定先へリダイレクト |
「いつ・何を決めるか」の違いを押さえておくと、使い分けの判断に役立ちます。
使い分けの判断基準
どちらのガードを使うべきかを判断するために、まずはシンプルな判断基準を考えてみました。
質問1: ルートパラメータ(:idなど)を使うか?
- YES →
canActivate- 例:
/users/:idでユーザーの存在チェック
- 例:
- NO → 次へ
質問2: 複数のルートをまとめて守りたいか?
- YES →
canMatch- 例: 管理画面配下のすべてのルートにログイン必須
- NO → 次へ
質問3: 同じパスでルートを分岐させたいか?
認証状態や権限によって、同じURLを別のルートに振り分けたいか
- YES →
canMatch- 例: ルートを「認証済みならダッシュボード」「未認証ならログイン」に分ける
- NO → 次へ
質問4: ルートマッチング前に弾きたい理由があるか?
- YES →
canMatch- 例: 機能フラグでルート自体を無効化
- NO →
canActivate
フロー図で表現するとこうなります。
この4つの質問に順番に答えていくことで、迷う場面はかなり減らせるのではないかと考えています。
実際にプロジェクトではどう使われていたか?
プロジェクト内の全ルートを対象に、上記の判断基準と照らし合わせて評価してみました。
| ガード | 利用箇所 | 基準準拠 | 見直し余地 |
|---|---|---|---|
canMatch |
58 | 55 (95%) | 3 (5%) |
canActivate |
67 | 40 (60%) | 27 (40%) |
canMatchはほぼ判断基準に沿って使われていましたが、canActivateについては、判断基準と照らし合わせて見直せそうなケースが約40%見つかりました。この評価を通じて、いくつかヒントになりそうな点を確認できました。
1. ルートパラメータを利用しているのに canMatch を使っている(3件)
ルートパラメータに直接アクセスできないため、URLセグメントを手動でパースする必要がある場合があります。
canActivate を使うことで、ルートパラメータに直接アクセスでき、扱いやすくなります。
2. 機能フラグチェックを canActivate で行っている(12件)
機能の有効/無効、プランや組織設定、ユーザー設定をチェックするガードなど。
ルート自体を無効化したい場合は、canMatch を使うことでルートマッチング前に弾け、不要な処理を避けられます。
3. 複数ルートを canActivate で個別に守っている(15件)
各ルートに個別に canActivate: [authGuard] を設定しているため、同じ認証チェックが複数回実行されます。
canMatch で親ルートを囲むことで、ルートマッチング前に一度だけ実行でき、パフォーマンス面でもメリットが期待できます。
4. 同一パスの条件分岐に canActivate を使っている(1件)
同じパスで複数のガードを組み合わせて条件分岐させています。
canMatch を使うことで、条件に応じて異なるルートに振り分けられ、不要なルートの処理を避けられます。
まとめ
本記事では、「まずは canMatch を起点に考え、ルートパラメータが必要な場合のみ canActivate」というシンプルな判断基準を1つの例として紹介し、実際のプロジェクトでどのように使われていたかを確認しました。
判断基準を明確にすることで、既存コードに対しても一定の評価を行えることが分かりました。
一方で、例えば canMatch でどこまでリダイレクトを担うべきかといった点など、判断基準として追加で考慮すべきものがありそうです。
このような点も含めて、チームとして方針を話し合い、一貫性ある運用を整えていくことが重要だと思います。
ここで紹介した判断基準や評価結果も踏まえつつ、まずは自分たちのチームで、ガード設計の方針を改めて見直していきたいと思います。
明日はフロントエンドエンジニアの @ic_lifewood さんの記事です!