Next.js _app.tsxでgetInitialiPropsをカスタマイズする


Authomatic Static Optimization


Next.js v9.3以降、データ取得用のgetInitialiPropsは、getStaticPropsとgetServerSidePropsに分離される.
Next公式ドキュメントのCustom Appを表示します.getInitialiPropsを使用する場合、自動状態Optimizationの機能は使用できないため、tsxでgetInitialiPropsを使用しないことをお勧めします.
function MyApp({ Component, pageProps }) {
  return <Component {...pageProps} />
}

// Only uncomment this method if you have blocking data requirements for
// every single page in your application. This disables the ability to
// perform automatic static optimization, causing every page in your app to
// be server-side rendered.
//
// MyApp.getInitialProps = async (appContext) => {
//   // calls page's `getInitialProps` and fills `appProps.pageProps`
//   const appProps = await App.getInitialProps(appContext);
//
//   return { ...appProps }
// }

export default MyApp
自動Static Optimizationとは何かを見てみましょう.
「次へ」は、getInitialiPropsまたはgetServerSidePropsがページに存在しない場合に静的ページとして認識され、構築時にhtmlファイルとして作成されます.これを構築時のpre-renderと呼ぶ.
このようにhtmlファイルを作成すると、ユーザーはリクエストを受信したときにサーバにhtmlを作成する必要がないため、ユーザーはページをすばやく表示することができます.
次の構築結果
.next/server/static/about.html
逆に、getInitalPropsまたはgetServerSidePropsがある場合は、htmlファイルを作成するのではなく、構築時にjsファイルを作成します.ユーザーが要求すると、nextサーバは必要なデータをサーバ側レンダリングにインポートし、完了したhtmlを返します.
次の構築結果
.next/server/static/about.js
だからapp.tsxにgetInitialiPropsを入れると、構築時にどのページも静的ページとして認識されないため、自動静的最適化は実現できません.

_app.tsxでgetInitialiPropsを使用する


私の場合、すべてのページが同じgetServerSidePropsをロードして動的Webを実現しています.静的ページは作成されていないため、自動静的最適化は実現できません.だから、コードがすべてのページで繰り返され、論理が複雑になるのを防ぐために、app.tsxはgetInitialiPropsを使用することにした.
サーバ側サイクル(Server Side Cycle)には、次のものがあります.
  • Next ServerはGETリクエストを受信します.
  • の要件を満たすページを探します.
  • _app.tsxのgetInitialiPropsがある場合は実行します.
  • Page ComponentのgetInitialiPropsがある場合に実行します.PagePropsの受信
  • _document.jsのgetInitialPropsがある場合は実行します.PagePropsの受信
  • はすべての道具、appを構成します.js>pageはコンポーネント順に表示されます.
  • は、すべてのコンテンツdocumentを構成します.jsを実行してhtml形式で出力します.
  • この過程でapp.tsxとpage.tsxでgetInitialiPropsとgetServerSidePropsが定義されている場合はpageです.tsxからロードされたpagepropsは上書きされます.だからapp.tsxのgetInitialiPropsをカスタマイズする必要があります.
    import type { AppContext } from 'next/app'
    
    function MyApp({ Component, pageProps }: AppProps): ReactElement {
      const queryClient = new QueryClient()
      const { theme } = pageProps as { theme: Theme }
      
      return (
        ...
      )
    }
    
    MyApp.getInitialProps = async ({ Component, ctx }: AppContext) => {
      let pageProps = {}
      if (Component.getInitialProps) {
        pageProps = await Component.getInitialProps(ctx)
      }
    
      const theme = await fetchTheme(ctx.req?.headers.referer)
    
      pageProps = { ...pageProps, theme }
    
      return { pageProps }
    }
    
    export default MyApp
    
    以上の{...pageProps, data}で受信したpagePropsを統合すると、アプリケーションはトピックデータと後続のpageにロードできます.tsxからロードされたpropsを統合して渡します.

    参考資料📕


    https://velog.io/@cyranocoding/Next-js-%EA%B5%AC%EB%8F%99%EB%B0%A9%EC%8B%9D-%EA%B3%BC-getInitialProps
    https://nextjs.org/docs/advanced-features/custom-app
    https://simsimjae.medium.com/next-js-automatic-static-optimization-b56ba8febea8