Next.js ではなぜ Link の中に <a>を入れる?なぜ href を Link に付ける??
始め
タイトルが雑ですね笑
昨日公式サイトでこのサンプルコードを見ていたら、ふいと浮かんだ疑問をそのままタイトルにしました。
import Link from 'next/link'
function Home() {
return (
<ul>
<li>
<Link href="/">
<a>Home</a>
</Link>
</li>
<li>
<Link href="/about">
<a>About Us</a>
</Link>
</li>
<li>
<Link href="/blog/hello-world">
<a>Blog Post</a>
</Link>
</li>
</ul>
)
}
export default Home
基本的な部分ですが、同じこと思った方に役に立てるかと思ってまとめます。
1. Link の中に a タグがなかったら?
まずは「Link
の中に<a>
がなかったらどうなる?」という純粋な疑問からといていきましょう。こういうのは直接試したほうが早いので試します。
サンプルコードは公式チュートリアルが提供してくれてるものを使いました。
1-1. Link の中文字列のみ
<h1 className="title">
Read{' '}
<Link href="/posts/first-post">
this page!
</Link>
</h1>
もしこのようにLink
の中にタグ自体がなくて文字列だけならどうなるか試します。
なんと、自動的に文字列がa
タグで囲まれましたー!Githubに公開されてるNext.jsのコードを見るとこの処理を担当してる部分が見つけられます。
// Deprecated. Warning shown by propType check. If the children provided is a string (<Link>example</Link>) we wrap it in an <a> tag
if (typeof children === 'string') {
children = <a>{children}</a>
}
ここで注目する部分はコメントですね。
Deprecated は重要度が低くて、今後廃止される可能性があるから使用しないことをオススメするという意味らしいです(初めて知った)。ですので、文字列だけ入れてもa
タグで囲んでくれる機能はなくなる可能性があるため、なるべく使わないようにしましょう。
1-2. 他のタグの場合
<h1 className="title">
Read{' '}
<Link href="/posts/first-post">
<span>this page!</span>
</Link>
</h1>
次はa
タグじゃなくて他のタグが入る場合です。実験ではspan
タグを入れてみました。
span
タグだけなので、先みたいに自動的にa
タグで囲んではくれないことがわかります。
でもクリックしたらちゃんとページ移動できたので、機能には問題ないようです。
おそらくページ移動機能がもともとLink
コンポーネントの機能なので中身のタグが変わっても影響がないのではと私は推測しています。
2. Link の中に a タグを入れる理由
ここでまた「Link
の中にa
タグがなくてもルーティングに問題ないのになぜa
タグを入れる必要がある?」と思いました。
気になってググってみたら stackoverflow の Why using a tag in nextjs Link? という質問で答えを見つけました。
It's for semantic html and SEO
This gives your rendered html proper semantics. This will help with your sites over all SEO. You can see examples and full explanation in the docs here.
semantic html と SEO のためにa
タグを入れましょう、ということですね。
Link
のお陰で<a>
がなく、他のタグがあってもページ移動機能には問題ありません。が、そうするともともと<a>
が持つべき機能を他のタグが持つようになるので semantic html を崩してしまいます。そして SEO にも悪影響を与えます。
semantic html を重要さをすっかり忘れていましたので、反省しました。
3.href を Link につける理由
最後に「なぜhref
を<a>
ではなくてLink
につけるのか」をときたいです。
3-1. Link
改めて公式チュートリアルに書いてるLink
の説明を見てみましょう。
<Link>
allows you to do client-side navigation to a different page in the application.
太字部分が大事です。
3-2. client-side navigation
Link
を使うとクライアント側でページ遷移ができます。これがLink
とa
タグの一番大きな違いだと思います。
公式チュートリアルで親切に確認方法まで教えてくれてますので、見てみましょう。
- ブラウザのディベロッパーツールで
<html>
の背景を黄色に変更します。 - 2つのページを行き来するためリンクをクリックします。
- ページ遷移の間も背景が黄色のままなことが確認できます。
クライアント側でルーティングしているため、リロードすることもなく背景色もそのまま維持されています。
もしa
タグでルーティングしてたらページ遷移の際にリロードが行われ、ディベロッパーツールで指定した背景色ももとに戻ります。
a
タグではなくてLink
でルーティングする理由もここにあります。ページ移動の度にリロードが行われるa
タグは SPA に適切ではないでしょう。
3-3. href は Link だけで充分
ここでまた気になったのが、「Link
と<a>
両方href
をつけるとどうなるのか?」でした。
<h1 className="title">
Read{' '}
<Link href="/posts/first-post">
<a href="/posts/first-post">this page!</a>
</Link>
</h1>
さっそく1で使ってたサンプルコードでをいじってやってみましょう。
結果はLink
のみhref
をつけたときと変わりませんね。<a>
にhref
つけてもちゃんと client-side navigation できているのかが気になったので、 3-2 で教わった通りディベロッパーツールで背景色を黄色にしたままページ移動を試しました。
リロードされてないからちゃんと client-side navigation できてますね!
Link
と<a>
両方href
をつけることとLink
だけhref
をつけることが同じ結果を出すので、<a>
にまでhref
をつける理由がなくLink
だけつけることになったのではないかと!私は思いました!
終わり
最初にLink
教わったときは単に「こういう書き方」だと言われましたけど、やはり気になった部分は検証したりググったりして解決したほうが気持ちいいですー!
Discussion
ご存じかもしれませんが。。。
ここはdeprecatedではなくなったようです。(その理由までは書いてませんが、コメントは削除されていました)
そうなんですね!!!気づいてませんでした、、共有ありがとうございます!!d=(´▽`)=b
とても参考になりました。ありがとうございます。
Next.js13からはLinkの子要素に<a>タグ入れると怒られるようになりましたw