前回
はじめに
前回はダッシュボードのレイアウトとページを作成しました。今回はユーザーがダッシュボードのルート間をナビゲートできるようにリンクを追加していきます。
ナビゲーションを最適化する理由
ページ間のリンクにはHTML要素である<a>タグを使用することができます。すでにサイドバーのリンクには<a>タグを使用していますので、実際にクリックして移動してみましょう。
クリックすると全ページが更新されていることが分かります。
<Link> コンポーネント
Next.jsでは<Link />コンポーネントを使用して、アプリケーション内のページ間をリンクすることができます。<Link>を使用すると、JavaScriptでクライアントサイドナビゲーションを行うことができます。
<Link />コンポーネントを使用するには、/app/ui/dashboard/nav-links.tsxを開き、next/linkからLinkコンポーネントをインポートします。
それでは、ナビゲーションで使用されている<a>タグを<Link>コンポーネントに置き換えてみましょう。
import {
UserGroupIcon,
HomeIcon,
DocumentDuplicateIcon,
} from '@heroicons/react/24/outline';
import Link from 'next/link';
// ...
export default function NavLinks() {
return (
<>
{links.map((link) => {
const LinkIcon = link.icon;
return (
<Link
key={link.name}
href={link.href}
className="flex h-[48px] grow items-center justify-center gap-2 rounded-md bg-gray-50 p-3 text-sm font-medium hover:bg-sky-100 hover:text-blue-600 md:flex-none md:justify-start md:p-2 md:px-3"
>
<LinkIcon className="w-6" />
<p className="hidden md:block">{link.name}</p>
</Link>
);
})}
</>
);
}このように、Linkコンポーネントは<a>タグを使用する方法と似ています。<a href="...">の代わりに<Link href="...">を使用するだけでいいのです。変更したら再度ページ遷移してページ更新の動きがあるかをチェックしましょう。これで、ページすべてを更新することなく、ページ間移動ができるようになりました。アプリケーションの一部はサーバー上でレンダリングされますが、ページ全体の更新はなく、ウェブアプリケーションのように感じることができます。
自動コード分割とプリフェッチ
ナビゲーションの体験を向上させるために、Next.jsはルートセグメントごとにアプリケーションを自動的にコード分割します。これはブラウザが初期ロード時にすべてのアプリケーションコードをロードする従来のReact SPAとは違います。
ルートによってコードが分割されることは、ページが分離されることを意味します。つまり、一つのページがエラーを投げてもアプリケーションの残りの部分は動作し続けることができます。
さらに、本番環境では<Link>コンポーネントがブラウザのビューポートに表示されるたびにNext.jsはリンク先のリートのコードをバックグラウンドで自動的にプリフェッチします。ユーザーがリンクをクリックするころには、リンク先のページのコードはすでにバックグラウンドで読み込まれているのです。
さらに詳しく知りたい方は公式ドキュメントの「Linking and Navigating」のHow Routing and Navigation Works」セクションを確認してください。
問題1
本番環境で、コンポーネントがブラウザのビューポートに表示されたとき、Next.jsは何をしますか?
- 追加CSSのダウンロード
- 画像のプリロード
- リンクされたルートのコードをプリフェッチする。
- リンクされたルートの遅延ロードを有効にする
3. リンクされたルートのコードをプリフェッチする。
Next.jsはリンク先のコードをバックグラウンドで自動的にプリフェッチします。 ユーザーがリンクをクリックするころには、リンク先ページのコードはすでにバックグラウンドで読み込まれています。
パターン:アクティブリンクの表示
一般的なUIパターンは、ユーザーが現在どのページにいるのかを示すために、アクティブなリンクを表示するというパターンです。このパターンを追加するにはURLからユーザーの現在のパスを取得する必要があります。Next.jsにはusePathname()というフックが用意されているので、それを使ってパスをチェックしこのパターンを実装することができます。
usePathname()はフックなので、nav-links.tsxをクライアント・コンポーネントにする必要があります。ファイルの先頭に'use client'ディレクティブを追加し、next/navigationからusePathname()をインポートします。
コードを以下のように変更しましょう。
'use client';
import {
UserGroupIcon,
HomeIcon,
InboxIcon,
} from '@heroicons/react/24/outline';
import Link from 'next/link';
import { usePathname } from 'next/navigation';
// ...続いて、<NavLinks />コンポーネント内のpathnameという変数にパスを代入します。
export default function NavLinks() {
const pathname = usePathname();
// ...
}CSS編で紹介したclsxライブラリを使用すれば、リンクがアクティブなときに条件付きでクラス名を運用できます。link.hrefがパス名と一致するとき、リンクは青いテキストと水色の背景で表示されるようになります。
最終的にはこの用意なりました。
'use client';
import {
UserGroupIcon,
HomeIcon,
DocumentDuplicateIcon,
} from '@heroicons/react/24/outline';
import Link from 'next/link';
import { usePathname } from 'next/navigation';
import clsx from 'clsx';
// ...
export default function NavLinks() {
const pathname = usePathname();
return (
<>
{links.map((link) => {
const LinkIcon = link.icon;
return (
<Link
key={link.name}
href={link.href}
className={clsx(
'flex h-[48px] grow items-center justify-center gap-2 rounded-md bg-gray-50 p-3 text-sm font-medium hover:bg-sky-100 hover:text-blue-600 md:flex-none md:justify-start md:p-2 md:px-3',
{
'bg-sky-100 text-blue-600': pathname === link.href,
},
)}
>
<LinkIcon className="w-6" />
<p className="hidden md:block">{link.name}</p>
</Link>
);
})}
</>
);
}サーバーが起動されていることを確認し、改めて確認してみましょう。

まとめ
- ページ間の移動で使用するナビゲーションは
<a>タグと<Link>コンポーネントを使用することが可能<a>タグは通常のページ遷移となる。<Link >コンポーネントはクライアントサイド・ナビゲーションとなる。ページすべてではなく、部分的な遷移となる。<Link>コンポーネントはルートセグメントごとにアプリケーションを分割するため、一部にエラーが起きても残りの部分は動作し続ける。- 本番環境で
<Link>コンポーネントを使用すると、リンク先のルートをプリフェッチするため、ユーザーがリンクをクリックするころには、すでにリンク先のコードが読み込まれている。

