【Next.js】Missing component: <Html />が出た時の対応備忘録

名称未設定のデザイン.png

問題

本サイトにGoogle Analyticsを導入するべく下記URLを参考に実装を行なった。

https://panda-program.com/posts/nextjs-google-analytics

https://sunday-morning.app/posts/2020-12-09-nextjs-google-analytics

しかし、ブランチをプッシュしたところ、Vercel側で以下のようなエラーが発生した。

09:43:17.891  Unhandled error during request: TypeError: Cannot read property 'type' of null09:43:17.891
      at /vercel/path0/.next/serverless/pages/_error.js:2013:1309:43:17.892
      at /vercel/path0/node_modules/react/cjs/react.production.min.js:17:388...

また`npm run dev`した際のTerminalのログを確認すると、以下のようなエラーが出てきた。

nodejs_1  | warn  - Your custom Document (pages/_document) did not render all the required subcomponent.
nodejs_1  | Missing component: <Html />
nodejs_1  | Read how to fix here: https://err.sh/next.js/missing-document-component

警告に出ている`page/_document.js`がこちら

import Document, { Head, Main, NextScript } from 'next/document' import { existsGaId, GA_ID } from '../lib/ga/gtag'

export default class MyDocument extends Document {
  render() {
    return (
      <html lang="ja">
        <Head>
          {/* Google Analytics */}
          {existsGaId && (
            <>
              <script async src={`https://www.googletagmanager.com/gtag/js?id=${GA_ID}`} />
              <script
                dangerouslySetInnerHTML={{
                  __html: `
                  window.dataLayer = window.dataLayer || [];
                  function gtag(){dataLayer.push(arguments);}
                  gtag('js', new Date());
                  gtag('config', '${GA_ID}', {
                    page_path: window.location.pathname,
                  });`,
                }}
              />
            </>
          )}
        </Head>
        <body>
          <Main />
          <NextScript />
        </body>
      </html>
    )
  }
}

原因

Next.jsでDocumentをカスタムする際は、<html>の代わりに<Html>が必要みたいです。

https://nextjs.org/docs/advanced-features/custom-document <Html><Head /><Main /> and <NextScript /> are required for the page to be properly rendered.

解決策

したがって、以下のように修正したところ、解決しました。

import Document, { Html, Head, Main, NextScript } from 'next/document'
import { existsGaId, GA_ID } from '../lib/ga/gtag'
export default class MyDocument extends Document {
  render() {
    return (
      <Html lang="ja">
        <Head>
          {/* Google Analytics */}
          {existsGaId && (
            <>
              <script async src={`https://www.googletagmanager.com/gtag/js?id=${GA_ID}`} />
              <script
                dangerouslySetInnerHTML={{
                  __html: `
                  window.dataLayer = window.dataLayer || [];
                  function gtag(){dataLayer.push(arguments);}
                  gtag('js', new Date());
                  gtag('config', '${GA_ID}', {
                    page_path: window.location.pathname,
                  });`,
                }}
              />
            </>
          )}
        </Head>
        <body>
          <Main />
          <NextScript />
        </body>
      </Html>
    )
  }
}