AsaDesign

Next.js(App Router)でヘッドレスCMS【③<head>解読】

自動生成されたHTMLを深堀りしたいと思います。

デフォルトの<head>要素を見てみた

開発者ツールをみると、<head>部分はこうなっていました。

<head>
 <!-- 文字エンコード指定(Next.jsの機能で自動追加される)-->
  <meta charset="utf-8">
  <!-- モバイルデバイスやタブレット向けのレスポンシブデザイン設定(Next.jsの機能で自動追加される)-->
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <!-- このページに対応させるCSSファイル -->
  <link rel="stylesheet" href="/_next/static/css/app/layout.css?v=1739239215938" data-precedence="next_static/css/app/layout.css">
  <link rel="preload" as="script" fetchpriority="low" href="/_next/static/chunks/webpack.js?v=1739239215938">
  <!-- Next.jsの内部スクリプトファイルを非同期に読み込む -->
  <script src="/_next/static/chunks/main-app.js?v=1739239215938" async=""></script>
  <script src="/_next/static/chunks/app-pages-internals.js" async=""></script>
  <script src="/_next/static/chunks/app/page.js" async=""></script>
  <meta name="next-size-adjust" content="">
  <!-- タブに表示されるタイトル -->
  <title>Create Next App</title>
  <!-- サイトの説明文 -->
  <meta name="description" content="Generated by create next app">
  <!-- アイコン読み込み -->
  <link rel="icon" href="/favicon.ico" type="image/x-icon" sizes="16x16">
  <script src="/_next/static/chunks/polyfills.js" nomodule=""></script>
  <!-- フォント読み込み -->
  <link rel="preload" href="/_next/static/media/569ce4b8f30dc480-s.p.woff2" as="font" crossorigin="" type="font/woff2">
  <link rel="preload" href="/_next/static/media/93f479601ee12b01-s.p.woff2" as="font" crossorigin="" type="font/woff2">
  <!-- SVGファイル読み込み -->
  <link rel="preload" href="/next.svg" as="image">
</head>

このコード全体は、Next.jsアプリケーションでページの読み込み速度を最適化するために、さまざまなリソース(CSS、JavaScript、フォント、画像)を効率的に読み込むための設定がされています。これにより、ユーザーがページを訪れたときに迅速でスムーズな体験が提供されることを目的としています。

ChatGPT
ChatGPTによるコード解説

このHTMLコードは、Next.jsを使って作成されたウェブアプリケーションの一部であり、いくつかの重要な要素が含まれています。それぞれについて説明します。

1. <meta charset="utf-8">

  • 目的: 文書の文字エンコードを指定します。utf-8は、世界中のほとんどの言語をサポートするため、ウェブで最も一般的に使用されるエンコードです。

2. <meta name="viewport" content="width=device-width, initial-scale=1">

  • 目的: モバイルデバイスやタブレット向けのレスポンシブデザインを設定します。これにより、ページがどのデバイスでも適切に表示されるように調整されます。width=device-widthはデバイスの画面幅を基準にし、initial-scale=1は初期ズームを設定します。

3. <link rel="stylesheet" href="/_next/static/css/app/layout.css?v=1739239215938" data-precedence="next_static/css/app/layout.css">

  • 目的: 外部のCSSファイル(スタイルシート)を読み込んでいます。hrefのURLはNext.jsアプリケーションが生成したもので、キャッシュを避けるためにバージョン番号(v=1739239215938)が付けられています。

4. <link rel="preload" as="script" fetchpriority="low" href="/_next/static/chunks/webpack.js?v=1739239215938">

  • 目的: webpack.jsというスクリプトファイルを事前に読み込むことを指定しています。rel="preload"は、ページの読み込みを最適化するために、早期にリソースを読み込むことを意味します。fetchpriority="low"は、このリソースの読み込み優先度を低く設定します。

5. <script src="/_next/static/chunks/main-app.js?v=1739239215938" async=""></script>

  • 目的: main-app.jsというJavaScriptファイルを非同期で読み込む設定です。async属性により、ページのレンダリングをブロックせずにスクリプトを読み込みます。

6. <script src="/_next/static/chunks/app-pages-internals.js" async=""></script>

  • 目的: Next.jsの内部スクリプトファイルを非同期に読み込む設定です。

7. <script src="/_next/static/chunks/app/page.js" async=""></script>

  • 目的: ページに関連するJavaScriptコードを非同期に読み込む設定です。

8. <meta name="next-size-adjust" content="">

  • 目的: Next.jsが内部的に使用するメタタグで、サイズ調整に関する情報を含んでいる可能性があります。このタグには値が設定されていません。

9. <title>Create Next App</title>

  • 目的: ウェブページのタイトルを設定します。この場合、Create Next Appという名前のタイトルがブラウザタブに表示されます。

10. <meta name="description" content="Generated by create next app">

  • 目的: ページの説明を提供します。この説明は、検索エンジンに表示される可能性があります。

11. <link rel="icon" href="/favicon.ico" type="image/x-icon" sizes="16x16">

  • 目的: ページのファビコン(ブラウザタブに表示される小さなアイコン)を設定します。favicon.icoという画像ファイルを使用しています。

12. <script src="/_next/static/chunks/polyfills.js" nomodule=""></script>

  • 目的: 古いブラウザ向けに必要なポリフィル(互換性を保つためのコード)を読み込むスクリプトです。nomodule属性は、モダンブラウザでは読み込まれないことを意味します。

13. <link rel="preload" href="/_next/static/media/569ce4b8f30dc480-s.p.woff2" as="font" crossorigin="" type="font/woff2">

  • 目的: フォントファイル(woff2形式)を事前に読み込む設定です。as="font"はリソースタイプがフォントであることを示し、crossoriginはクロスオリジンのリクエストを許可する設定です。

14. <link rel="preload" href="/_next/static/media/93f479601ee12b01-s.p.woff2" as="font" crossorigin="" type="font/woff2">

  • 目的: 上記と同様に別のフォントファイル(woff2形式)を事前に読み込む設定です。

15. <link rel="preload" href="/next.svg" as="image">

  • 目的: next.svgという画像ファイルを事前に読み込む設定です。

このコード全体は、Next.jsアプリケーションでページの読み込み速度を最適化するために、さまざまなリソース(CSS、JavaScript、フォント、画像)を効率的に読み込むための設定がされています。これにより、ユーザーがページを訪れたときに迅速でスムーズな体験が提供されることを目的としています。

Next.js(App Router)の<head> どこで設定されてる??

初期状態でのapp/layout.tsxは、ご覧の通り<head>がありません。どこにあるんだ?

import type { Metadata } from "next";
import { Geist, Geist_Mono } from "next/font/google";
import "./globals.css";
import Head from "next/head";

const geistSans = Geist({
  variable: "--font-geist-sans",
  subsets: ["latin"],
});

const geistMono = Geist_Mono({
  variable: "--font-geist-mono",
  subsets: ["latin"],
});

export const metadata: Metadata = {
  title: "Create Next App",
  description: "Generated by create next app",
};

export default function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode;
}>) {
  return (
    <html lang="en">
      <Head></Head>
      <body
        className={`${geistSans.variable} ${geistMono.variable} antialiased`}
      >
        {children}
      </body>
    </html>
  );
}

ChatGPTに聞いてみた

Next.jsのApp Routerを使っている場合、<head>タグの設定は少し異なります。App Router(app/ディレクトリ)は、ページごとに異なる<head>要素を設定する方法を提供しています。以下の方法で<head>を設定できます。

1. app/layout.js または app/layout.tsx での設定

App Routerを使用している場合、app/layout.js(または app/layout.tsx)でアプリ全体のレイアウトを設定します。このファイル内で、<head>タグを設定できます。レイアウトはすべてのページに適用されるため、共通の<head>設定をここで行います。

// 例: app/layout.js
import Head from 'next/head';

export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <Head>
        <meta name="description" content="This is my website" />
        <meta name="viewport" content="width=device-width, initial-scale=1" />
        <link rel="icon" href="/favicon.ico" />
        <title>My Next.js App</title>
      </Head>
      <body>{children}</body>
    </html>
  );
}

2. ページ単位での <head> 設定

App Routerを使っている場合、ページごとに異なる<head>要素を設定したいときは、各ページのコンポーネント内でnext/headを使用します。App Routerでは、個別のページコンポーネントは通常app/{page}.jsのように存在します。

例えば、app/page.js内でページごとの<head>を設定できます。

// 例: app/page.js (ホームページ)
import Head from 'next/head';

export default function HomePage() {
  return (
    <>
      <Head>
        <title>Home Page</title>
        <meta name="description" content="Welcome to the home page" />
      </Head>
      <h1>Welcome to My App!</h1>
    </>
  );
}

このように、各ページで個別に<Head>を使ってタイトルやメタ情報を設定することができます。

3. 動的な <head> 設定

ページ単位で動的に<head>を設定する場合もnext/headを使って、コンポーネントの状態やプロパティに応じて、ページのタイトルやメタ情報を変更できます。

// 例: app/products/[id].js (製品詳細ページ)
import { useRouter } from 'next/router';
import Head from 'next/head';

export default function ProductPage() {
  const router = useRouter();
  const { id } = router.query;

  return (
    <>
      <Head>
        <title>Product {id}</title>
        <meta name="description" content={`Details about product ${id}`} />
      </Head>
      <h1>Product {id}</h1>
    </>
  );
}

まとめ

  • グローバルな<head>設定: app/layout.js(または app/layout.tsx)で、サイト全体の共通の<head>要素を設定します。
  • ページごとの<head>設定: 各ページ(app/page.jsapp/products/[id].jsなど)で、next/headを使って個別に設定します。

App Routerを使用している場合、<head>はレイアウトとページごとに分けて設定できるので、柔軟に管理ができます。

私の感想

追加設定できるのは分かったけど、何も設定してない時の<head>の説明がありません。

公式サイトで事実確認

<head>タグを使わないでください

export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html>
      <body>{children}</body>
    </html>
  )
}

ルート レイアウトでは、 <html>タグと <body>タグを定義する必要があります。
ルート レイアウトに や <meta> などの <head> タグを手動で追加しないでください。代わりに、ストリーミングや <head> 要素の重複排除などの高度な要件を自動的に処理するメタデータ API を使用する必要があります。

layout.js – Next.js

<head>タグの代わりに<Head>を使ってください

<head>要素の使用を防止します。
<head>要素を使用してページレベルのメタデータを含めましたが、これにより Next.js アプリケーションで予期しない動作が発生する可能性があります。代わりに Next.js の組み込み next/head コンポーネントを使用してください。

No Head Element – Next.js
import Head from 'next/head'
 
function IndexPage() {
  return (
    <div>
      <Head>
        <title>My page title</title>
      </Head>
      <p>Hello world!</p>
    </div>
  )
}
 
export default IndexPage

メタデータを設定していない場合でも2つのメタタグが自動で設定されます

デフォルトフィールド

metaルートでメタデータが定義されていない場合でも常に追加される2 つのデフォルト タグがあります。

  • メタ文字セットタグ:ウェブサイトの文字エンコーディングを設定します。
  • メタビューポートタグ:さまざまなデバイスに合わせて Web サイトのビューポートの幅とスケールを設定します。
メタデータ – Next.js
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />

まとめ

Next.js(App router)の<head>について

  • 何も設定しなくても最低限のものはNext.jsの機能で自動生成される
  • titleとかdescriptionはmetadataAPIというものを使って設定する
  • <head>の代わりに<Head>を使う
  • ページごとのlayout.tsxで<Head>の設定ができる