🐶
Next.js

Next.js App and Document Usage Guide

By Filip on 04/21/2024

Learn the difference between Next.js's `_app.js` and `_document.js` and how they impact customization and control over your application's rendering.

Next.js App and Document Usage Guide

Table of Contents

Introduction

In Next.js development, two key files, _app.js and _document.js, offer distinct customization capabilities. Let's delve into their roles and how they empower you to tailor your application.

Step-by-Step Guide

Next.js provides two special files, _app.js and _document.js, for customizing your application's behavior and structure. Let's explore each file and its purpose:

1. _app.js:

  • Global Application Component: This file acts as the entry point for your entire application. It wraps all your page components and allows you to define shared layouts, global styles, and state management solutions.
  • Customizing App Behavior: You can use _app.js to:
    • Implement global error handling.
    • Add global CSS styles.
    • Wrap your application with context providers (e.g., for state management or themes).
    • Inject additional data into pages using getInitialProps.
  • Example:
// _app.js
import '../styles/globals.css';
import { ThemeProvider } from 'next-themes';

function MyApp({ Component, pageProps }) {
  return (
    <ThemeProvider attribute="class">
      <Component {...pageProps} />
    </ThemeProvider>
  );
}

export default MyApp;

2. _document.js:

  • Customizing HTML Structure: This file allows you to modify the HTML document structure of your Next.js application. You can add custom meta tags, link tags, scripts, or modify the document's body.
  • Controlling Head and Body: Use _document.js to:
    • Set the document's language.
    • Add meta tags for SEO or social media sharing.
    • Include external scripts or stylesheets.
    • Modify the document's body structure.
  • Example:
// _document.js
import Document, { Html, Head, Main, NextScript } from 'next/document';

class MyDocument extends Document {
  render() {
    return (
      <Html lang="en">
        <Head>
          <meta name="description" content="My awesome Next.js app" />
        </Head>
        <body>
          <Main />
          <NextScript />
        </body>
      </Html>
    );
  }
}

export default MyDocument;

Key Differences:

  • Scope: _app.js affects the React component tree, while _document.js affects the HTML document structure.
  • Purpose: _app.js is for customizing application behavior and shared logic, while _document.js is for customizing the HTML document and its elements.

When to Use Which:

  • Use _app.js when you need to apply changes that affect all pages, such as global styles, layouts, or state management.
  • Use _document.js when you need to modify the HTML document structure, add custom meta tags, or include external scripts.

Remember: Both files are optional, and you only need to create them if you need to customize the default behavior of your Next.js application.

Code Example

The provided code snippets demonstrate how to utilize _app.js and _document.js files within a Next.js application. The _app.js file serves as the entry point for every page, enabling global error handling, CSS style inclusion, and context provider wrapping. On the other hand, the _document.js file allows customization of the HTML document structure, including setting the language, adding meta descriptions, and incorporating external scripts.

Based on the provided information, here are some JavaScript examples demonstrating how to use _app.js and _document.js in a Next.js application:

_app.js Examples:

1. Implementing Global Error Handling:

// _app.js
import Error from 'next/error';

function MyApp({ Component, pageProps, err }) {
  if (err) {
    // Handle the error here, e.g., display a custom error page
    return <Error statusCode={err.statusCode} title={err.message} />;
  }
  return <Component {...pageProps} />;
}

export default MyApp;

2. Adding Global CSS Styles:

// _app.js
import '../styles/globals.css'; // Import your global CSS file

function MyApp({ Component, pageProps }) {
  return <Component {...pageProps} />;
}

export default MyApp;

3. Wrapping with Context Provider (e.g., ThemeProvider):

// _app.js
import { ThemeProvider } from 'next-themes';

function MyApp({ Component, pageProps }) {
  return (
    <ThemeProvider defaultTheme="light" attribute="class">
      <Component {...pageProps} />
    </ThemeProvider>
  );
}

export default MyApp;

_document.js Examples:

1. Setting Document Language and Adding Meta Description:

// _document.js
import Document, { Html, Head, Main, NextScript } from 'next/document';

class MyDocument extends Document {
  render() {
    return (
      <Html lang="en">
        <Head>
          <meta name="description" content="My awesome Next.js app" />
        </Head>
        <body>
          <Main />
          <NextScript />
        </body>
      </Html>
    );
  }
}

export default MyDocument;

2. Including External Script:

// _document.js
import Document, { Html, Head, Main, NextScript } from 'next/document';

class MyDocument extends Document {
  render() {
    return (
      <Html>
        <Head>
          <script src="https://example.com/external-script.js"></script>
        </Head>
        <body>
          <Main />
          <NextScript />
        </body>
      </Html>
    );
  }
}

export default MyDocument;

Remember: These are just basic examples. You can customize and extend the functionality of _app.js and _document.js based on your specific application requirements.

Additional Notes

Further Considerations for _app.js:

  • Data Fetching: While getInitialProps can be used in _app.js to fetch data for all pages, be cautious as it can impact performance if not optimized. Consider using getServerSideProps or getStaticProps within individual page components for more granular data fetching.
  • Layout and Styling: _app.js is ideal for implementing consistent layouts across your application. You can create a layout component and render it within _app.js, ensuring all pages share the same structure. Similarly, global styles defined in _app.js will apply to all pages.
  • State Management: If you're using a state management library like Redux or Context API, _app.js is a good place to wrap your application with the necessary providers, making state accessible to all components.

Further Considerations for _document.js:

  • SEO Optimization: Utilize _document.js to add meta tags relevant to SEO, such as title, description, and keywords. This helps search engines understand your content and improve your website's ranking.
  • Accessibility: Enhance accessibility by setting the appropriate language attribute in the Html tag and ensuring proper semantic structure within the document.
  • Third-Party Scripts: If you need to include external scripts that require specific placement within the HTML document (e.g., before the closing body tag), _document.js provides the necessary control.

Advanced Use Cases:

  • Customizing Error Pages: You can create custom error pages for different HTTP status codes by overriding the getInitialProps method in _app.js and rendering the appropriate error component based on the error status.
  • Internationalization: Implement internationalization (i18n) by using libraries like next-i18next and configuring language settings in _app.js or _document.js.
  • Analytics and Tracking: Integrate analytics and tracking scripts into your application by adding them to the Head component within _document.js.

Remember: Always test your customizations thoroughly to ensure they don't introduce unintended side effects or performance issues.

Summary

Feature _app.js _document.js
Purpose Customizes application behavior and shared logic. Customizes HTML document structure and elements.
Scope React component tree (affects all pages) HTML document structure
Use Cases Global styles, layouts, state management, error handling, data injection Meta tags, external scripts/styles, document language, body structure modification
Example Wrapping app with ThemeProvider for global theming. Adding meta description tag for SEO.

Conclusion

In conclusion, _app.js and _document.js are powerful tools in Next.js for customizing your application's behavior and structure. Understanding their distinct roles and use cases allows you to create a tailored and optimized user experience. By leveraging these files effectively, you can enhance your application's functionality, performance, and overall user satisfaction. Remember to choose the appropriate file based on your specific customization needs and always test your changes thoroughly to ensure a seamless and efficient application.

References

Were You Able to Follow the Instructions?

😍Love it!
😊Yes
😐Meh-gical
😞No
🤮Clickbait