Next.jsアプリケーションで外部リンクとリダイレクトの実装方法

Next.jsでの外部リンクおよびリダイレクト

Next.jsのアプリケーションで外部ページへのリンクを追加する方法について、疑問を持っている方もいるかもしれません。

実際には非常に簡単ですが、組み込みのLinkコンポーネントについて少し混乱するかもしれません。

この記事では、外部URLを指すリンクを追加する方法とリダイレクトの方法を紹介します。

Linkコンポーネント

Next.jsは、アプリケーション内のページ間のナビゲーションを簡単に実現するために組み込みの「Link」コンポーネントを提供しています。

この強力なコンポーネントは、クライアント側のトランジションとプリロードルートを活用することで、スムーズで高速なユーザーエクスペリエンスを実現するのが特長です。

例えば、アプリ内の異なるページへの遷移は以下のように簡単に実現できます。

import Link from 'next/link';

//...

<Link href="/about">
  <a>About Us</a>
</Link>

しかしながら、重要な点を理解しておく必要があります。

Linkコンポーネントはアプリケーション内のページ遷移にのみ適しており、外部のWebサイトへのリダイレクトには使用できません。

外部URLに対しては、通常のアンカータグを使用するか、必要に応じてリダイレクト処理を別途実装する必要があります。

また、注意が必要なのはLinkタグとアンカータグの間に余分なスペースを挿入しないことです。

例えば、以下のようにスペースを挿入するとエラーが発生します。

//✖︎
// <Link href="/"> <a> Home </a> </Link>

//◎
<Link href="/"><a>Home</a></Link>

これは、Linkコンポーネントが1つの子要素のみを許容するため、スペースが子要素として解釈されることによるものです。

これはアプリケーションの動作を妨げる可能性があるため、注意が必要です。

まとめると、Next.jsの「Link」コンポーネントはアプリケーション内のページ間のナビゲーションに非常に便利ですが、外部Webサイトへのリダイレクトや余分なスペースの挿入には注意が必要です。

適切に利用することで、ユーザーエクスペリエンスを向上させることができます。

詳細な使用方法や他の注意点については、Next.js公式ドキュメントや当ブログ記事を参照してみてください。

外部リンク

以下は、外部リンクになるため、単純にアンカータグを使用してこの機能を処理できます。

export default function Home() {
  return (
    <div>
<a href="https://dev-k.hatenablog.com/archive">My blog page</a>
    </div>
  )
}

Linkは通常のアンカータグのすべてのプロパティをサポートしていないことに気付いている方もいるかと思います。

たとえば、targetプロパティを指定して新しいタブ(ウィンドウ)でリンクを開く簡単な方法はありません。

基本的には、外部リンクなのでLinkコンポーネントを使用する必要はありません。

これは、外部のウェブページへのリンクは通常、クライアントサイドでのページ遷移ではなく、リンク先のウェブサイトへのリンクとして扱われるべきだからです。

ですがLinkを使用して、外部リンクとして新しいタブで開きたい場合ではどうしたらいいでしょうか?

外部リンクを新しいタブで開く方法については、通常のアンカータグの全てのプロパティをサポートしていないことがありますが、Linkコンポーネントを使用して実現することが可能です。

以下のコードを参考にして、外部リンクを新しいタブで開くための方法を説明します。

// 外部リンクを新しいタブで開くためのコンポーネント
import Link from 'next/link';

export default function Home() {
  return (
    <div>
      <Link href="https://dev-k.hatenablog.com/archive" passHref>
        <a target="_blank" rel="noopener noreferrer">My blog page</a>
      </Link>
    </div>
  );
}

ここで、LinkコンポーネントのpassHref属性を使用して、hrefプロパティを子要素のアンカータグに渡します。

そして、アンカータグにtarget="_blank"とrel="noopener noreferrer"を追加することで、外部リンクを新しいタブで開くことができます。

SEO的な観点からは、passHrefを使ってアンカータグにhrefを渡すことが重要です。また、セキュリティ対策として、rel="noopener noreferrer"を追加することをお忘れなく。

これにより、バニラアンカータグを使用するよりも安全に外部リンクを新しいタブで開くことができます。

以上の方法を用いて、外部リンクを新しいタブで開く機能を実装してみてください。

しかし、SEOやセキュリティの観点から常に慎重に対処することを忘れないでください。

また、できる限りバニラアンカータグを使用することが望ましいです。

外部ページへのリンクを実現する際には、Next.jsプロジェクトではバニラアンカータグの使用が推奨されます。

公式ドキュメントによれば、外部URLへの移動や/pagesによらないリンクは、Linkコンポーネントを使用する必要がなく、代わりにアンカータグを活用することを勧めています。

ただし、<a>タグを使う際には必ずhref属性を指定しましょう。この属性には有効かつ移動可能なアドレスを記述します。

また、キーボードでのアクセシビリティを考慮するためにも、href属性が必要です。

href属性を指定できない場合には、リンクの挙動を実現するために適切なスタイルを設定したボタンを使用して、onClickイベントを活用しましょう。

これにより、アクセシビリティを保ちながらリンク先への移動をサポートできます。

もし外部リンクのURLがプロジェクト内のファイルである場合でも、Next.jsはスマートに対応してくれます。

Linkコンポーネント内でpublic/などを含める必要はありません。以下のように指定するだけで外部リンクが実現できます。

<Link href="./NameFile/Name.png">
  <a target="_blank">
    {ここにコードを記述...}
  </a>
</Link>

以上のように、「Link」コンポーネントはページ遷移に使用するものであり、外部ページへのリンクにはバニラアンカータグを使うことが推奨されます。

必ずhref属性を指定し、必要に応じてonClickイベントや適切なスタイルを適用して、外部リンクを実現しましょう。

これにより、ウェブサイトの使いやすさとアクセシビリティを向上させることができます。

外部URLへのリダイレクト

外部URLにユーザーをリダイレクトする方法を説明します。

Next.jsを使用して、next.config.jsファイルにリダイレクトルールを追加することで実現できます。

まず、プロジェクトのルートディレクトリにあるnext.config.jsファイルを開きます。

このファイルには、async関数を使用してリダイレクトルールを追加します。

// next.config.js

module.exports = {
  async redirects() {
    return [
      {
        source: '/Home', // リダイレクトをトリガーするパスを指定します。
        destination: 'https://dev-k.hatenablog.com/archive', // リダイレクト先のURLを指定します。
        permanent: true, // リダイレクトを永続的にするかどうかを指定します。ここでは、trueに設定しています。
      },
    ];
  },
};

上記の例では、"/Home"パスへのすべてのリクエストが、「https://dev-k.hatenablog.com/archive」に永久的にリダイレクトされます。

permanentパラメータがtrueに設定されているため、ブラウザは指定されたURLに永久的にリダイレクトされます。

これらの値がリクエスト内で満たされた場合にのみリダイレクトが実行されます。

// next.config.js

module.exports = {
  async redirects() {
    return [
      {
        has: [
          {
            type: 'header', // リクエストのヘッダーを指定します。
            key: 'host', // ヘッダーの名前を指定します。ここでは、ホストの情報を取得します。
            value: 'localhost:3000', // ヘッダーの値を指定します。ここでは、ローカルの開発サーバーを指定します。
          },
        ],
        source: '/Home', // リダイレクトをトリガーするパスを指定します。
        destination: 'https://dev-k.hatenablog.com/archive', // リダイレクト先のURLを指定します。
        permanent: true, // リダイレクトを永続的にするかどうかを指定します。ここでは、trueに設定しています。
      },
    ];
  },
};

上記のように、hasオプションを使用することで、リクエストパラメータを元にリダイレクトを制御することも可能です。

hasオプションには、value、key、typeの3つのプロパティを指定します。これらを使って条件に基づいてリダイレクトを実行します。

permanent: trueとしているため、ブラウザは元のURLを保持し、再度アクセスしても自動的にリダイレクト先に転送されます。

これにより、特定の条件(ここではヘッダーの値)に基づいてリダイレクトを実行することができます。

たとえば、特定のヘッダーが存在する場合にのみリダイレクトを実行したい場合は、以下のように設定します。

// next.config.js

module.exports = {
  async redirects() {
    return [
      {
        // リダイレクトの条件を指定します。ここでは、リクエストのヘッダーに特定の値がある場合にリダイレクトを実行します。
        has: [
          {
            type: 'header', // リクエストのヘッダーを指定します。
            key: 'X-Custom-Header', // ヘッダーの名前を指定します。
            value: 'archive', // ヘッダーの値を指定します。
          },
        ],
        source: '/archive', // リダイレクトをトリガーするパスを指定します。
        destination: 'https://dev-k.hatenablog.com/archive', // リダイレクト先のURLを指定します。
        permanent: false, // リダイレクトを永続的にするかどうかを指定します。ここでは、falseに設定しています。
      },
    ];
  },
};

この設定は、X-Custom-Headerという名前のヘッダーがarchiveという値を持つリクエストに対してのみ、/archiveのパスにアクセスした場合に、「https://dev-k.hatenablog.com/archive」にリダイレクトします。

permanent: falseとしているため、リダイレクトは一時的なものとなり、ブラウザは元のURLを保持します。

hasオプションを使うことで、より柔軟なリダイレクトの制御が可能になります。

以上が、Next.jsを使用してユーザーを外部URLにリダイレクトする方法の詳細な説明です。

この機能を利用するには、Next.jsのバージョンが9.5.0以上であることを確認してください。

他の方法でリダイレクト

Next.jsを使用すると、ページをビルド時にプリレンダリングしてリダイレクトを設定する方法はいくつかあります。

注意点がございます。

Next 13.3以降では、Reactアプリでのデータの取得方法が完全に変更されています。

データの取得はgetServerSideProps()、getStaticProps()、getInitialPath()などのデータフェッチメソッドに精通していると思います。

しかし、残念ながらNext.js 13.3以降では、これらのメソッドはアンチパターンとみなされ、使用は非推奨になっていますのでバージョンの確認をお願いします。

ここでは例として、getStaticPropsを利用してビルド時にリダイレクトを設定する方法を示します。

// getStaticPropsはNext.jsの静的生成時に実行される関数です。
// この関数を使用すると、ビルド時にページをプリレンダリングし、リダイレクトを設定できます。
export async function getStaticProps() {
  const sample = null;

  // sampleがnullの場合、リダイレクトを実行します。
  if (!sample) {
    return {
      redirect: {
        permanent: false, // permanentがfalseの場合、リダイレクトは一時的なものとなります。
        destination: '/Home', // リダイレクト先のパスを指定します。
      },
    };
  }

  // sampleがnullでない場合は、通常のプロパティを返します。
  // この場合、propsオブジェクトは空ですが、必要に応じてデータを追加できます。
  return {
    props: {},
  };
}

上記のコードでは、getStaticPropsを使ってページをビルド時にプリレンダリングし、sampleの値に応じてリダイレクトを設定しています。

sampleがnullの場合は指定されたdestinationにリダイレクトしますが、そうでなければ通常のPropsを返します。

また、useEffectフックを使用してリダイレクトを実装する方法もあります。

次の例では、useEffect内でwindow.location.hrefを使って外部URLにリダイレクトしています。

import { useEffect } from 'react';

export default function Home() {
  useEffect(() => {
    window.location.href = "https://dev-k.hatenablog.com/archive";
  }, []);

  return (
    <div>
      <h2></h2>
    </div>
  );
}

さらに、window.location.replaceメソッドを使用することでも、外部URLにリダイレクトできます。

import { useEffect } from 'react';

export default function Home() {
  useEffect(() => {
    window.location.replace("https://dev-k.hatenablog.com/archive");
  }, []);

  return (
    <div>
      <h2></h2>
    </div>
  );
}

これらの方法を使用することで、ボタンのクリックやチェックボックスのチェックなど、プログラム内で外部リンクを開くことができます。

カスタムページを作成し、必要に応じてこれらの方法を利用して外部リンクを開くことができます。

ただし、Next.jsはサーバーサイドレンダリングを実現するためのフレームワークであり、通常のブラウザ環境とは異なり、「windowオブジェクト」は定義されていません。

しかし、useEffectフック内では「windowオブジェクト」にアクセスすることができます。

useEffectフック内でwindowにアクセスできる理由については、以下のリンク先で詳しく解説しています。

dev-k.hatenablog.com

最後に

Next.jsのLinkコンポーネントは同じアプリ内でのページ遷移に最適であり、クライアントサイドでのページ遷移を高速化することができます。

外部のリンクにはアンカータグ<a>を使用することで、適切なリンク挙動を実現します。

本記事が皆様の理解に役立てば幸いです。

もし役に立った場合は、ぜひブックマークや共有をお願いいたします。

それでは、本日は以上とさせていただきます。

最後までお読みいただき、ありがとうございました。

プライバシーポリシー

© 2023 Icons8 LLC. All rights reserved.

© [deve.K], 2023. React logo is a trademark of Facebook, Inc. JavaScript is a trademark of Oracle Corporation and/or its affiliates. jQuery and the jQuery logo are trademarks of the JS Foundation. TypeScript and the TypeScript logo are trademarks of the Microsoft Corporation. Next.js and the Next.js logo are trademarks of Vercel, Inc. Firebase and the Firebase logo are trademarks of Google LLC. All logos edited by [deve.K].