tk1024.net

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

tk1024 / tk1024.net

Next.jsのSSRでpreloadする

Published 2024-08-23 12:00:00
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 を利用して出力します。

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/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

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

1import type { Metadata } from 'next'
2 
3export const metadata: Metadata = {
4  title: 'My Page Title',
5}
6 
7export default function Page() {
8  return '...'
9}

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

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 に移行してもエラーがでないのに出力もされていないという気づき辛いところでした。