tk1024.net

メモとSNSリンクが載っています

tk1024 / tk1024.net

Next.jsのSSRでpreloadする

Published 2024-08-23 12:00 · by tk1024
Next.jsReact.js

概要

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 を利用して出力します。

import Head from "next/head";

export default function HOME() {
  return (
    <Head>
      <link rel="preload" href="/path/to/image.ext" as="image" />
    </Head>
  );
}

出力されるHTMLは次のようになります。

<!-- 略 -->
 <head>
<!-- 略 -->
    <link rel="preload" href="/path/to/image.ext" as="image" />
<!-- 略 -->
</head>
<!-- 略 -->

<link rel="preload" href="/path/to/image.ext" as="image" /> が出力されています。
想定通りの動きです。

App Router にそのまま移行するとうまくいかない

これをそのまま App Router に移すと次のような出力になります。

<!-- 略 -->
<head>
<!-- 略 -->
<!-- 略 -->
</head>
<!-- 略 -->

<link rel="preload" href="/path/to/image.ext" as="image" /> が出力されなくなりました。

主な原因は next/headApp Router でサポートされなくなったからです。

In the pages directory, the next/head React component is used to manage <head> HTML elements such as title and meta . In the app directory, next/head is replaced with the new built-in SEO support.

Upgrading: App Router Migration | Next.js

つまり、 次のような記述を期待されるようになりました。

import type { Metadata } from 'next'
 
export const metadata: Metadata = {
  title: 'My Page Title',
}
 
export default function Page() {
  return '...'
}

しかし、preloadMetadata では扱えませんので別のアプローチが必要です。

App Router で preload を使う

まず、App Router で preload を扱う方法は用意されていません。

では、どうなったのかというと React.js の preload というAPIを利用するようになっています。 (ちなみにこのAPIはまだカナリア版です)
preload – React

もう React.js の API の話なので Next.js かどうかは関係ないですが、 先程の Next.js のコードは次のように書き換えられます。

import { preload } from 'react-dom';

export default function HOME() {
  preload("/path/to/image.ext", {
    as: "image",
  });

  return null;
}

この出力は次のようになります

<!-- 略 -->
<head>
<!-- 略 -->
    <link rel="preload" href="/path/to/image.ext" as="image" />
<!-- 略 -->
</head>
<!-- 略 -->

ということで、めでたしめでたし。

React.js の API なので Next.js のドキュメントからは発見できないし、まず next/head をそのまま App Router に移行してもエラーがでないのに出力もされていないという気づき辛いところでした。