The _document page in Next.js is a crucial file that determines the HTML structure of your application. It's used to define the layout and content of your pages.
The _document page is a special page in Next.js that's used to wrap every page in your application. This means that the _document page is rendered on every page load.
In Next.js, the _document page is a React component that's responsible for rendering the HTML structure of your application. It's typically located in the pages directory.
Understanding the _document page is essential for developers who want to customize the layout and behavior of their Next.js application.
Troubleshooting
Troubleshooting next.js _document issues can be a challenge, but it's essential to start by reviewing your code to identify where you're accessing the document object. This could be in lifecycle methods, outside components, or in third-party libraries.
One crucial check is to ensure that the problematic code runs only on the client side. A simple if (typeof window !== 'undefined') check can help determine if you're in a browser environment.
Outdated dependencies can also cause issues, so make sure your Next.js and other related packages are up to date. This can often resolve problems without requiring further investigation.
Understanding the Error
The document is not defined error in Next.js usually occurs when your code tries to access the document object, a part of the browser's global window object, during server-side rendering.
Next.js uses Node.js for server-side rendering, which doesn't have access to the document object. This disconnect is the root cause of the error.
Developers transitioning from client-side JavaScript frameworks often encounter this issue because accessing the document object is a regular practice in those frameworks.
Preliminary Checks
Before you start digging into complex solutions, it's essential to perform some preliminary checks to ensure you're on the right track. This step can save you a lot of time and frustration in the long run.
First, review your code to identify where you're accessing the document object. This could be in lifecycle methods, outside components, or in third-party libraries.
It's also crucial to ensure that the problematic code runs only on the client side. A simple check like `if (typeof window !== 'undefined')` can help determine if you're in a browser environment.
Sometimes, outdated dependencies can cause issues. Make sure your Next.js and other related packages are up to date.
To help you stay organized, here are the preliminary checks you can perform:
- Review your code for document object access.
- Check if the code runs on the client side using `if (typeof window !== 'undefined')`.
- Update your Next.js and other related packages.
Customizing Next.js Document
You can customize the Next.js document by creating a custom _document.js file in your pages directory. This file allows you to augment your application's HTML and body tags.
To create a custom _document.js file, simply add a _document.js file in your pages directory. Direct manipulation of document or browser APIs will still cause issues, so it's mainly used for initial setup.
The _document.js file is only rendered on the server, so EventListeners like onClick will not work. This means you can't use it for client-side logic.
To override the default Next.js document, you need to create the _document.tsx file in the Pages directory. This file should export a default function called document, and return the HTML, head, and next script.
The document is like the top-level HTML structure of your Next.js application. You can introduce custom behavior like fonts, scripts, icons, etc. in this file.
To add custom behavior, you can import HTML components, the head component main, and next script from the next/document package. This will allow you to customize the HTML tag, add third-party scripts, link custom fonts, and add analytics scripts.
The document is only rendered in the server, so direct manipulation of document or browser APIs will still cause issues. However, you can use it to add the language property to the HTML, or change the favicon.
By creating a custom _document.tsx file, you can also add support for localization, change the favicon, and add your analytics scripts or link custom CSS, custom fonts, etc.
Next.js with Material-UI
Next.js with Material-UI is a great combination, but it does require some updating to work seamlessly.
Next.js needs some updating to serve the correct styles on initial render, which is why updating the existing pages/_document.tsx is necessary.
To handle this, you should update the existing pages/_document.tsx to generate the css content and include it in the output so the content is styled correctly on initial load.
The getInitialProps in _document.tsx does the bulk of the work needed to make this happen.
By restarting your application via npm run dev, you should see the correct styles on initial render.
If everything works, you should see the styled content when you restart the application.
Applying Global Styles
You can apply global styles to the theme by moving environment variables into the Material-UI theme. This keeps all styles in a centralized pattern.
In the previous part of the tutorial, environment variables were used to control the background color and font color of the page. These variables are now being moved into the Material-UI theme.
Removing style tags from the _document.tsx file is the first step in applying global styles. The new main MyDocument class should look like this.
By reloading the page, the styles will be applied to the body.
Sources
- https://nextjs.org/docs/pages/api-reference/components/script
- https://codedamn.com/news/nextjs/how-to-fix-document-is-not-defined-in-next-js
- https://kumarsahani.medium.com/confused-between-app-js-and-document-js-files-in-next-js-say-no-more-61dfa754e430
- https://egghead.io/lessons/typescript-override-the-default-next-js-document
- https://hashnode.blainegarrett.com/building-a-github-repo-template-part-6-material-ui-with-nexttypescript-ckcuvhqsf00dr7os1gdq2altu
Featured Images: pexels.com