概要
Next.jsで全体のCSS設定をしたいというご質問を頂いたので、_document.js(tsx)
と_app.js(tsx)
について。
この2つはpages/ディレクトリに設置し、Routeにならない特殊なファイルです。
_document.js(tsx)
は吐き出されるHTMLファイルの構成を変えることができ、_app.js(tsx)
はすべてのRouteコンポーネントがここで書いた<App>
コンポーネントによってラップされるようになります。
_document.js(.tsx)
_documet.js(tsx)
はDocument コンポーネントを継承したクラスを実装します。
Headタグの中に<title>
など、全ページ共通の設定を行うことができます。
class SampleDocument extends Document {
static async getInitialProps(ctx) {
const initialProps = await Document.getInitialProps(ctx)
return { ...initialProps }
}
render() {
return (
<Html lang={this.props.locale.split("-")[0]}>
<Head>
<meta name="viewport" content="width=device-width,height=device-height" key="viewport" />
<link rel="shortcut icon" href="/static/shortcut-icon.png" key="shortcutIcon" />
<meta name="theme-color" content="#087da1" key="themeColor" />
<link rel="dns-prefetch" href="//www.google.co.jp" />
</Head>
<body>
<Main />
<NextScript />
</body>
</Html>
)
}
}
export default SampleDocument
注意点としては以下のことがあります。
- SSR(サーバサイドレンダリング)のみの実行なので、クライアントサイドの処理を書くべきではありません。
-
<Main />
内に入る外部のReactコンポーネントはブラウザによって初期化されないため、ここでアプリケーションのロジックや、styled-jsxのようなCSSを設定してはいけません。代わりに_app.js(tsx)を使ってください - DocumentのgetInitialPropsは、クライアントサイドの遷移中には呼び出されず、ページが静的に最適化されている場合にも呼び出されません
_app.js(tsx)
_app.js(tsx)
はデフォルトのAppコンポーネントを上書きできます。
全ページで必要な処理をここに書くことができます。他にも以下のようなことができます
- ページ間の共通レイアウトを持たせることができる
- 共通のstateを持つことができる
- グローバルなCSS(全ページ共通の)を定義できる
- componentDidCatchを利用したカスタムエラー処理
- 各Routeコンポーネントをラップするもの
- ReduxのProvider設定をする
また、_document.js(tsx)
と異なり、AppはPageコンポーネントと同じ動きをするので、_app.js(tsx)
はSSRされ、ライフサイクル周りのイベントはクライアントサイドでも実行することができます。
なお、すべてのページで必要な依存物を全て詰め込んでしまうと、サーバーサイドレンダリングでそのRouteにとって無駄な処理をしてしまう上、Next.jsが自動的にコード分割をできなくなってしまい、HTTPで配信されるJSファイルのサイズも肥大化してしまいます。各Routeで必要なだけ参照するようにするという形を取ることも時には検討した方が良いです。
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
まとめ
Next.jsでは_document.js(tsx)
, _app.js(tsx)
を用いることでページ間の共通処理や共通レイアウトを定義することができます。
参考
https://nextjs.org/docs/advanced-features/custom-document
https://nextjs.org/docs/advanced-features/custom-app