Next.jsのLinkを外部リンクで使うと何が問題?初学者向けに解説
Next.jsを使っていると、ページ間の移動にLink
コンポーネントを使うのが一般的ですよね。でも、「外部リンク(たとえば、https://example.com)にLink
を使うのはダメなの?」と疑問に思ったことはありませんか?
実は、Next.jsの公式ドキュメントでは、外部リンクにはLink
コンポーネントではなく、普通の<a>
タグを使うことが推奨されています。なぜそうなのか、どんな問題が起こるのか、初心者でもわかるようにやさしく解説します! 図や例も使って、イメージしやすく説明するので、ぜひ最後まで読んでみてください!
Link
コンポーネントの役割を理解しよう
1. まず、Link
コンポーネントがどんな役割を持っているのか見てみましょう。Link
は、Next.jsのアプリ内でページを移動する(たとえば、/home
から/about
へ)ときに使う特別なツールです。以下の2つの機能が、ページ移動を「超高速」にしてくれます:
-
クライアントサイドナビゲーション:
通常の<a>
タグでページを移動すると、ブラウザがサーバーに新しいページをリクエストして、ページ全体をリロードします。これ、ちょっと時間がかかりますよね。Link
はJavaScriptを使って、必要な部分だけを更新するので、ページがサクッと切り替わります! -
プリフェッチ(事前読み込み):
Link
は、ユーザーがリンクをクリックする前に、リンク先のページのデータをバックグラウンドで読み込んでおきます。たとえば、<Link href="/about">About</Link>
があると、Next.jsは「この人は/aboutに行くかも!」と予測して、データを準備。クリックした瞬間にページが表示されるので、めっちゃ速く感じます!
イメージ図:
[ブラウザ]
↓ <Link href="/about">About</Link>
↓ プリフェッチ:/aboutのデータを準備
↓ ユーザーがクリック
[サクッと/aboutページを表示!]
この仕組みのおかげで、Next.jsのアプリはスムーズで快適なんです!
Link
を使うと、なぜダメ?
2. 外部リンクででは、外部リンク(たとえば、https://example.com)にLink
を使うと、どんな問題が起こるのでしょうか? 実は、Link
は**アプリ内のページ(内部リンク)**向けに作られているので、外部リンクには向いていません。以下に、具体的な問題を3つ挙げます。
(1) プリフェッチが無意味になる
Link
は、リンク先のデータを事前に読み込もうとします。でも、外部リンク(例:https://example.com)はNext.jsのアプリの外にあるので、プリフェッチできません。
例:
<Link href="https://example.com">外部サイト</Link>
この場合、Next.jsは「https://example.comのデータを準備しよう!」と頑張りますが、外部サイトなので何もできません。無駄な処理が走るだけ。これが「オーバーヘッド(余計な負荷)」です。まるで、コンビニに行くのに遠回りしているようなものです。
イメージ図:
[ブラウザ]
↓ <Link href="https://example.com">外部サイト</Link>
↓ プリフェッチを試みる
↓ 外部サイトなので準備できない!(無駄な処理)
↓ ユーザーがクリック
[結局、普通にページが開く]
(2) クライアントサイドナビゲーションが使えない
Link
の「ページをリロードせずに切り替える」機能は、Next.jsアプリ内のページでしか使えません。外部リンクの場合、ブラウザが普通に新しいページをリロードするだけなので、Link
のメリットがゼロ。無駄にLink
のJavaScript処理が走るだけです。
(3) 余計なJavaScriptの処理
Link
はクリックイベントをJavaScriptで処理します。外部リンクなら、ブラウザに「新しいページを開いて」と伝えるだけでいいのに、Link
を使うと、Next.jsが「このリンクはアプリ内かな?」とチェックする処理が走ります。これも小さなオーバーヘッドになります。
<a>
タグがベスト!
3. 外部リンクには外部リンクには、シンプルに<a>
タグを使うのが一番です。理由は以下の通り:
-
シンプルで効率的:
<a>
タグはブラウザに「このURLを開いて」と直接伝えるので、余計な処理がありません。 -
外部リンクに最適:検索エンジンやスクリーンリーダーも
<a>
タグを正しく認識します。 -
セキュリティもバッチリ:
target="_blank"
で新しいタブを開くとき、rel="noopener noreferrer"
を付ければ、安全性も確保できます。
推奨コード:
<a
href="https://example.com"
target="_blank"
rel="noopener noreferrer"
className="text-blue-600 hover:underline"
>
外部サイトへ
</a>
-
target="_blank"
:新しいタブでリンクを開く。 -
rel="noopener"
:新しいタブから元のページを操作されないようにする(セキュリティ)。 -
rel="noreferrer"
:リファラ情報を送らない(プライバシー)。
ユーザー体験の工夫:
外部リンクだとわかるように、リンクの横にアイコンを付けるのも親切です!
<a
href="https://example.com"
target="_blank"
rel="noopener noreferrer"
className="text-blue-600 hover:underline"
>
外部サイトへ
<svg className="inline w-4 h-4 ml-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"/>
</svg>
</a>
4. 「でも、Linkで統一したい!」という場合
「内部リンクも外部リンクもLink
で統一したい!」という場合、以下のようにpassHref
を使う方法もありますが、あまりおすすめしません:
import Link from 'next/link';
<Link href="https://example.com" passHref>
<a target="_blank" rel="noopener noreferrer">
外部サイトへ
</a>
</Link>
この方法は、結局<a>
タグの動作に頼るので、Link
のメリットがなく、複雑になるだけ。素直に<a>
タグを使う方がシンプルです。
もっとスマートな方法:
内部リンクと外部リンクを統一的に扱いたいなら、カスタムコンポーネントを作ると便利です!
import Link from 'next/link';
function CustomLink({ href, children, ...props }) {
const isExternal = href.startsWith('http') || href.startsWith('//');
if (isExternal) {
return (
<a href={href} target="_blank" rel="noopener noreferrer" {...props}>
{children}
</a>
);
}
return (
<Link href={href} {...props}>
<a>{children}</a>
</Link>
);
}
export default CustomLink;
使い方:
<CustomLink href="https://example.com">外部サイトへ</CustomLink>
<CustomLink href="/about">内部ページへ</CustomLink>
これなら、コードがスッキリして、内部リンクも外部リンクも一貫して扱えます!
5. まとめ
-
外部リンクには
<a>
タグを使おう:Link
コンポーネントは内部リンク向け。外部リンクに使うと、プリフェッチやJavaScriptの処理が無駄な「オーバーヘッド」になる。 -
セキュリティとユーザー体験を忘れずに:
target="_blank"
にはrel="noopener noreferrer"
を必ず付けて、外部リンクだとわかる工夫を。 -
カスタムコンポーネントでスマートに:内部リンクと外部リンクを統一したいなら、
CustomLink
コンポーネントが便利!
Next.jsのLink
コンポーネントは超便利ですが、使う場所を間違えると「遠回り」になってしまいます。
Discussion