1

I'm deploying a NextJS app to Vercel and I use styled-components. This is my _document.tsx file:

import Document from 'next/document'
import { ServerStyleSheet } from 'styled-components'
import flush from 'styled-jsx/server'

export default class MyDocument extends Document {
  static async getInitialProps(ctx) {
    const sheet = new ServerStyleSheet()
    const originalRenderPage = ctx.renderPage

    try {
      ctx.renderPage = () =>
        originalRenderPage({
          enhanceApp: (App) => (props) =>
            sheet.collectStyles(<App {...props} />),
        })

      const initialProps = await Document.getInitialProps(ctx)
      const styledJSXStyles = flush()
      return {
        ...initialProps,
        styles: (
          <>
            {initialProps.styles}
            {sheet.getStyleElement()}
            {styledJSXStyles}
          </>
        ),
      }
    } finally {
      sheet.seal()
    }
  }
}

The error I'm seeing from Vercel is that document is not defined at new StyleSheet:

02:22:23    > Build error occurred
02:22:23    ReferenceError: document is not defined
02:22:23        at new StyleSheet (/vercel/workpath0/node_modules/styled-jsx/dist/lib/stylesheet.js:40:35)
02:22:23        at new StyleSheetRegistry (/vercel/workpath0/node_modules/styled-jsx/dist/stylesheet-registry.js:26:33)
02:22:23        at Object.<anonymous> (/vercel/workpath0/node_modules/styled-jsx/dist/style.js:15:26)
02:22:23        at Module._compile (internal/modules/cjs/loader.js:1063:30)
02:22:23        at Object.Module._extensions..js (internal/modules/cjs/loader.js:1092:10)
02:22:23        at Module.load (internal/modules/cjs/loader.js:928:32)
02:22:23        at Function.Module._load (internal/modules/cjs/loader.js:769:14)
02:22:23        at Module.require (internal/modules/cjs/loader.js:952:19)
02:22:23        at require (internal/modules/cjs/helpers.js:88:18)
02:22:23        at Object.<anonymous> (/vercel/workpath0/node_modules/styled-jsx/dist/server.js:9:14)
02:22:23        at Module._compile (internal/modules/cjs/loader.js:1063:30)
02:22:23        at Object.Module._extensions..js (internal/modules/cjs/loader.js:1092:10)
02:22:23        at Module.load (internal/modules/cjs/loader.js:928:32)
02:22:23        at Function.Module._load (internal/modules/cjs/loader.js:769:14)
02:22:23        at Module.require (internal/modules/cjs/loader.js:952:19)
02:22:23        at require (internal/modules/cjs/helpers.js:88:18)

I was under the assumption that using SeverStyleSheet in my document file would have fixed this situation, but it does not seem to be the case.

Here are the things I've tried since:

  • Updating _document.tsx (shown above) to support styled-components and styled-jsx (I don't use the latter, this is a dependency part of NextJS and the source of the error)
  • Attempted to build locally (builds just fine with npm run build)
  • Check for presence of the window object in index.tsx and _app.tsx
  • Checking for the presence of window.fetch before calling fetch in any component
  • Commented out a rendered iFrame w/ dangerouslySetInnerHTML

What have I not yet considered?

2 Answers 2

1

You can test your _document.tsx with this example:

import React from 'react'
import Document, {
  DocumentContext,
  DocumentInitialProps,
  Head,
  Html,
  Main,
  NextScript
} from 'next/document'
import { ServerStyleSheet } from 'styled-components'

export default class MyDocument extends Document {
  static async getInitialProps(
    ctx: DocumentContext
  ): Promise<DocumentInitialProps> {
    const sheet = new ServerStyleSheet()
    const originalRenderPage = ctx.renderPage

    try {
      ctx.renderPage = () =>
        originalRenderPage({
          enhanceApp: App => props => sheet.collectStyles(<App {...props} />)
        })

      const initialProps = await Document.getInitialProps(ctx)
      return {
        ...initialProps,
        styles: (
          <>
            {initialProps.styles}
            {sheet.getStyleElement()}
          </>
        )
      }
    } finally {
      sheet.seal()
    }
  }

  render(): JSX.Element {
    return (
      <Html lang="en">
        <Head>
          <title>your app title</title>
          <meta charSet="utf-8" />
        </Head>
        <body>
          <Main />
          <NextScript />
        </body>
      </Html>
    )
  }
}
Sign up to request clarification or add additional context in comments.

1 Comment

did you face any problem using styled-components in Next JS? I mean problems with SEO.
1

It turns out the issue was with an older version of NextJS, bumping my version from 10.0.6 to 10.0.9 resolved this.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.