Home>

I am developing using next.js, react, styled-components.
The layout of the screen collapses for a moment during the initial drawing.
I think it's probably because I'm using SSR, but I don't know how to solve it, so I posted it.
If anyone knows, I want you to teach me

// Addendum

import React from'react';
import NextDocument, {
  Head,
  Main,
  NextScript,
  DocumentInitialProps,
  DocumentContext,
} from'next/document';
import {ServerStyleSheet} from'styled-components';
class Document extends NextDocument {
  static async getInitialProps (ctx: DocumentContext): Promise<DocumentInitialProps>{
    const sheet = new ServerStyleSheet ();
    const originalRenderPage = ctx.renderPage;
    ctx.renderPage = (): ReturnType<DocumentContext ['renderPage']>=>
      originalRenderPage ({
        enhanceApp: (App) =>(props) =>sheet.collectStyles (),
      });
    const initialProps = await Document.getInitialProps (ctx);
    return {
      ... initialProps,
      styles: [... React.Children.toArray (initialProps.styles), sheet.getStyleElement ()],
    };
  }
  render () {
    return (
    <Head>
      <meta name = "viewport" content = "width = device-width, initial-scale = 1.0, shrink-to-fit = no" />
      <body>
        <Main />
        <NextScript />
      </body>
    </Head>
    );
  }
}
export default Document;
  • Answer # 1

    Preface

    This answer assumes that the problem is caused by styled-components. If the problem is not solved even after following the steps below, is the style sheet loaded by the CSS import function of Next.js (example:import styles from'../styles/SomeStyle.module.css')please confirm. If you are using this feature, the CSS import feature of Next.js does not support SSR and you will need to style it with another approach. If you are using styled-componentscreateGlobalStyleIs recommended.

    Answer

    In order to perform SSR correctly with styled-components, it is necessary to make special settings.

    Below are the steps to add settings to an existing Next.js app:

    SSR setup Prepare .babelrc

    To the root of the app.babelrcIf the file does not exist, add it..babelrcThe minimum required contents of are as follows:

    {
      "presets": ["next/babel"],
      "plugins": []
    }

    next/babelIsnextIt is included in the package and does not need to be installed.

    Add babel plugin

    First, use one of the following commandsstyled-componentsInstall the babel plugin:

    # npm
    npm i -D babel-plugin-styled-components
    # yarn
    yarn add -D babel-plugin-styled-components
    # pnpm
    pnpm add -D babel-plugin-styled-components

    Once the installation is complete.babelrcList the plugins added to:

    {"presets": ["next/babel"],
      "plugins": ["styled-components"]
    }

    In this statedevRun the script and see if the following line is printed correctly:

    info --Using external babel configuration from /.../.babelrc

    After checking the outputdevExit the script once.

    If the output is not correct or an error occurs, check that the file is correctly configured according to this procedure.

    Use ServerStyleSheet with customized Document class

    pages/_document. [jt] sx?Customized by putting the file inDocumentYou can use the class. (Next.js defaultDocumentYou can check the class here. ) Of this classstatic getInitialPropsExtend the static method with the following code:

    // The following 3 lines of `import` statement are required
    import React from'react'
    import Document, {DocumentContext, DocumentInitialProps} from'next/document'
    import {ServerStyleSheet} from'styled-components'
    export default class MyDocument extends Document {
      // Extension from here ~
      static async getInitialProps (
        ctx: DocumentContext
      ): Promise<DocumentInitialProps>{
        const sheet = new ServerStyleSheet ()
        const originalRenderPage = ctx.renderPage
        ctx.renderPage = (): ReturnType<DocumentContext ['renderPage']>=>    originalRenderPage ({
            enhanceApp: (App) =>(props) =>sheet.collectStyles (),})
        const initialProps = await Document.getInitialProps (ctx)
        return {
          ... initialProps,
          styles: [
            ... React.Children.toArray (initialProps.styles),
            sheet.getStyleElement ()
          ],,
        }
      }
      // ~ Extension so far
    }
    Extended Document testing

    againdevRun the script and check if the CSS is rendered correctly with JavaScript turned off in your browser.

    If it is working properly, the server console will output a log similar to the following:

    ready --started server on http: // ...
    info --Using external babel configuration from ... /. Babelrc
    event --compiled successfully
    event --build page: /
    wait --compiling ...
    event --compiled successfully

    Setup is completed.

    If you have any questions, please feel free to ask in the comments.