Next.jsのSSRでpreloadする
概要
Next.js v14 では App Router と Page Router の2種類のルーター方式をサポートしています。
App Router と Page Router とでは色々な違いがありますが、今回扱うのがその一つである preload
です。
App Router と Page Router の preload の使い方
Page Router で preload を使う
Page Routerでは next/head
を利用して出力します。
1import Head from "next/head";
2
3export default function HOME() {
4 return (
5 <Head>
6 <link rel="preload" href="/path/to/image.ext" as="image" />
7 </Head>
8 );
9}
出力されるHTMLは次のようになります。
1<!-- 略 --> 2 <head> 3<!-- 略 --> 4 <link rel="preload" href="/path/to/image.ext" as="image" /> 5<!-- 略 --> 6</head> 7<!-- 略 -->
<link rel="preload" href="/path/to/image.ext" as="image" />
が出力されています。
想定通りの動きです。
App Router にそのまま移行するとうまくいかない
これをそのまま App Router
に移すと次のような出力になります。
1<!-- 略 --> 2<head> 3<!-- 略 --> 4<!-- 略 --> 5</head> 6<!-- 略 -->
<link rel="preload" href="/path/to/image.ext" as="image" />
が出力されなくなりました。
主な原因は next/head
が App Router
でサポートされなくなったからです。
In the
pages
directory, thenext/head
React component is used to manage<head>
HTML elements such astitle
andmeta
. In theapp
directory,next/head
is replaced with the new built-in SEO support.
Upgrading: App Router Migration | Next.js
つまり、 次のような記述を期待されるようになりました。
1import type { Metadata } from 'next'
2
3export const metadata: Metadata = {
4 title: 'My Page Title',
5}
6
7export default function Page() {
8 return '...'
9}
しかし、preload
は Metadata
では扱えませんので別のアプローチが必要です。
App Router で preload を使う
まず、App Router で preload を扱う方法は用意されていません。
では、どうなったのかというと React.js の preload というAPIを利用するようになっています。 (ちなみにこのAPIはまだカナリア版です)
preload – React
もう React.js の API の話なので Next.js かどうかは関係ないですが、 先程の Next.js のコードは次のように書き換えられます。
1import { preload } from 'react-dom';
2
3export default function HOME() {
4 preload("/path/to/image.ext", {
5 as: "image",
6 });
7
8 return null;
9}
この出力は次のようになります
1<!-- 略 --> 2<head> 3<!-- 略 --> 4 <link rel="preload" href="/path/to/image.ext" as="image" /> 5<!-- 略 --> 6</head> 7<!-- 略 -->
ということで、めでたしめでたし。
React.js の API なので Next.js のドキュメントからは発見できないし、まず next/head
をそのまま App Router
に移行してもエラーがでないのに出力もされていないという気づき辛いところでした。