😊

Next.jsのLinkを外部リンクで使うと何が問題?初学者向けに解説

に公開

Next.jsを使っていると、ページ間の移動にLinkコンポーネントを使うのが一般的ですよね。でも、「外部リンク(たとえば、https://example.com)にLinkを使うのはダメなの?」と疑問に思ったことはありませんか?

実は、Next.jsの公式ドキュメントでは、外部リンクにはLinkコンポーネントではなく、普通の<a>タグを使うことが推奨されています。なぜそうなのか、どんな問題が起こるのか、初心者でもわかるようにやさしく解説します! 図や例も使って、イメージしやすく説明するので、ぜひ最後まで読んでみてください!

1. Linkコンポーネントの役割を理解しよう

まず、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のアプリはスムーズで快適なんです!

2. 外部リンクでLinkを使うと、なぜダメ?

では、外部リンク(たとえば、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が「このリンクはアプリ内かな?」とチェックする処理が走ります。これも小さなオーバーヘッドになります。

3. 外部リンクには<a>タグがベスト!

外部リンクには、シンプルに<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