今回は、Next.js で全体の設定ができる_document.js(tsx)
と_app.js(tsx)
について解説してききます ✍️
_document.js(.tsx)
Next.js の Page コンポーネントはデフォルトでは<html>・<body>
タグの定義を行いますが、それらを拡張したい場合は _document.js(tsx)
を作成し、その中で Document
コンポーネントを継承したクラスを実装しましょう。
class SampleDocument extends Document {
static async getInitialProps(ctx) {
const initialProps = await Document.getInitialProps(ctx);
return { ...initialProps };
}
render() {
return (
<Html>
<Head>
<link rel="dns-prefetch" href="//www.google.co.jp" />
</Head>
<body>
<Main />
<NextScript />
</body>
</Html>
);
}
}
export default SampleDocument;
_document.js(tsx)
では、<Html>
, <Head />
, <Main />
, <NextScript />
がページが適切にレンダリングするために必要となります。この Head タグの中に<title>
など、全ページ共通の設定を行います。
また注意点としては以下のことがあります。
- **SSR(**サーバサイドレンダリング)のみの実行なので、クライアントサイドの処理を書くべきではありません。← 間違いやすいので注意してください!
<Main />
内に入る外部の React コンポーネントはブラウザによって初期化されないため、ここでアプリケーションのロジックや、styled-jsx のような CSS を設定してはいけません。全てのページのコンポーネントに共通させたい場合は代わりにApp
コンポーネントを使ってください(_app.js(tsx)
に定義)Document
のgetInitialProps
は、クライアントサイドの遷移中には呼び出されず、ページが静的に最適化されている場合にも呼び出されません
次に、_app.js(tsx)
の説明をしていきます。
_app.js(tsx)
Next.js ではApp
コンポーネントを使用して全てのページを初期化するようになっています。 そのため、このコンポーネントを継承したクラスがあるファイル、_app.js(tsx)
を作成することでデフォルトの App コンポーネントを上書きできます。
つまり、 全ページで必要な処理をここに書くことができます。他にも App コンポーネントでは以下のようなことができます
- ページ間の共通レイアウトを持たせることができる
- 共通の state を持つことができる
- グローバルな CSS(全ページ共通の)を定義できる
componentDidCatch
を利用したカスタムエラー処理- 各 Route コンポーネントをラップするもの
- Redux の Provider 設定をする
import * as React from "react";
import { Provider } from "react-redux";
function MyApp({ Component, pageProps }) {
return (
<Provider store={store}>
<Layout>
<Component {...pageProps} />
<style jsx global>
{`
#container {
min-width: 800px;
}
`}
</style>
)}
</Layout>
</Provider>
);
}
export default MyApp;
また、_document.js(tsx)
と異なり、App は Page コンポーネントと同じ動きをするので、_app.js(tsx)は SSR され、ライフサイクル周りのイベントはクライアントサイドでも実行することができます。
まとめ
Next.js では Document, App コンポーネントを用いることでページ間の共通処理や共通レイアウトを定義することができます!
_document.js(tsx)
には Document コンポーネントを継承したクラスを実装し、共通レイアウトを定義し、_app.js(tsx)
では App コンポーネントを継承したクラスを定義し、全ページで共通の処理などを書きましょう!
上手く使い分けて、快適な Next ライフを送ってください!👨💻