26
13

More than 1 year has passed since last update.

Next.jsの_documment..tsxと_app.tsxについてメモ

Posted at

_app.tsxとは

/page/_app.tsxを作成することでAppコンポーネントをカスタマイズができる。
すべてのページコンポーネントの初期化に使われるコンポーネント。
すべてのページで共通な処理などを書くことができる。

_documment.tsxとは

/page/_documment.tsxを作成することでDocumentコンポーネントをカスタマイズができる。
htmlタグやbodyタグの定義を行うコンポーネント
ページ共通のheadタグなどを定義する

_app.tsxの例

_app.jsx
import { AppProps } from 'next/app'
import Head from 'next/head'

const App = ({ Component, pageProps }: AppProps) => (
  <>
    <Head>
      <title />
        <meta name='viewport' content='width=device-width, initial-scale=1' />
    </Head>
    <Component {...pageProps} />
  </>
)

export default App

_documents.tsxの例

_documents.jsx
import NextDocument, { Html, Head, Main, NextScript } from 'next/document'

type Props = {}

class Document extends NextDocument<Props> {
  render() {
    return (
      <Html lang="ja-JP">
        <Head>
          <meta charSet="utf-8" />
          <meta name="format-detection" content="telephone=no" />
          <link rel="shortcut icon" href={'/favicon.ico'} />
          <link rel="apple-touch-icon" href={'/logo.png'} />
        </Head>
        <body>
          <Main />
          <NextScript />
        </body>
      </Html>
    )
  }
}

export default Document

※NextDocumentクラスの継承が必要

_app.tsxと_documents.tsxは全ページ共通に設置しておきたい処理を記述できます。
アナリティクスタグなんかも設置していいと思います。

注意点として_documents.tsxには
<title />タイトルタグや
<meta name='viewport' content='width=device-width, initial-scale=1' />metaのviewportは設置すると怒られるみたいなので、
_app.tsxに記述しましょう。

Contextで共通なグローバルな値を管理する

_app.tsxは全ページ共通になるので、グローバルな値を管理するのにも使えます。
カスタムhookにAppContextがあるていです。

_app.jsx
import { AppProps } from 'next/app'
import Head from 'next/head'
import { AppContext } from '@hooks/useApp'
const App = ({ Component, pageProps }: AppProps) => (
  const value = ''
  <>
    <Head>
      <title />
        <meta name='viewport' content='width=device-width, initial-scale=1' />
    </Head>
    <AppContext.Provider value={value}>
      <Component {...pageProps} />
    </AppContext.Provider>
  </>
)

export default App

こんな感じで_app.tsxにContextを設置しておけばグローバルな値として、
全てのページで共通の値を使えます。

ページごとにmetaなどを変えたい場合

ページによってタイトルやmeta情報を変更したい場合があると思います。
まずはheadタグまとめたコンポーネントを作ってあげます。

head.jsx
import * as React from 'react';
import Head from 'next/head';

export default ({ title, description, keyword, image, url }: Props) => {
  return (
    <Head>
      <title>{title}</title>
      <meta property="og:title" content={title} />
      <meta property="og:description" content={description} />
      <meta name="keywords" content={keyword} />
      <meta property="og:type" content="blog" />
      <meta property="og:url" content={url} />
      <meta property="og:image" content={image} />
      <meta property="og:site_name" content={title} />
      <meta name="twitter:card" content="summary" />
      <meta name="twitter:site" content="text.jp" />
      <meta name="twitter:url" content={image} />
      <meta name="twitter:title" content={title} />
      <meta name="twitter:description" content={description} />
      <meta name="twitter:image" content={image} />
    </Head>
  );
};
test.jsx
import Head from 'next/head';

function testPage() {
  return (
    <>
      <Head 
          title={'タイトル'}
          description={'ディスクリプション'}
          keyword={'キーワード'}
          image={'/img.jpg'}
          url={'https://test.jp'}
       />
    </>
  );
}

export default testPage;

こうしてあげると各ページごとにタイトルやmetaを設定することができます。

_documment..tsxと_app.tsxについてと
ちょっとした派生的な実装をご紹介いたしました。
(実際に動かしたわけではないので、なにかあればご指摘いただけますと幸いです。。)

26
13
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
26
13