How To Load Static CSS and JS Files in Next.js
Tags: react, javascript
Published: 2020-11-21 21:48:21

Recently I was working on a project that required conversion from a static HTML/CSS/JS theme to a Next.js application. I had done some hardcore React before so making a switch to Next.js wasn't that hard, it was pretty simple, to be honest, and I also wanted to benefit from the API routes availability and SEO advantages of using Next.js due to its server-side rendering capabilities. One of the issues I didn't take into consideration was the server-side rendering effect on normal `js` files execution. This ended up taking my entire week as I tried to figure out a way to integrate `js` files without painting my Chrome console red.

For me, this was a pretty straightforward situation, all I had to do was to import the `css` and `js` files into `index.html` file, but wait, Next.js doesn't have an `index.html` file. This was my first issue. Fortunately, after a little bit of research in the [Next.js documentation](https://nextjs.org), I figured it out(kind of). So, to import `js` and `css` files, it's pretty easy. In the `pages` directory, create a `_document.js` file and add the code below.


```jsx
import Document, { Html, Head, Main, NextScript } from 'next/document'

class MyDocument extends Document {
  static async getInitialProps(ctx) {
    const initialProps = await Document.getInitialProps(ctx)
    return { ...initialProps }
  }

  render() {
    return (
      <Html>
        <Head>
			<link rel="stylesheet" href="styles.css"/>
		</Head>
        <body>
          <Main />
          <NextScript />
          <script src="main.js"></script>
        </body>
      </Html>
    )
  }
}

export default MyDocument

```

**Note:** To call the `css` and `js` as above, the files need to be available in the `public` folder on the root of the project.

The above code works as expected under normal circumstances. `CSS` files are rendered and work as expected, however, when using `JS`, since some properties such as `window`  are only available on the client-side, it throws errors. I had this problem, particularly when trying to use `owl.min.js` and `wow.min.js` files for slideshows because they utilize `window`. The most common error I faced was the one below:

```bash
Warning: Extra attributes from the server: style in nav (at DefaultNavbar.tsx:38)
```
After a bit of research, I got a variety of solutions, which were really awesome and helpful, like checking if `window` exists inside the lifecycle method `componentDidMount` and then load the library, while this was helpful, I didn't know how I could load the static `js` files. So, after struggling for almost a week, I finally managed to load the `js` files without any errors as follows:

In the code above, while loading a `js` file, add the `async={true}` property which loads the `script` file when ready.

```jsx
import Document, { Html, Head, Main, NextScript } from 'next/document'

class MyDocument extends Document {
  static async getInitialProps(ctx) {
    const initialProps = await Document.getInitialProps(ctx)
    return { ...initialProps }
  }

  render() {
    return (
      <Html>
        <Head>
			<link rel="stylesheet" href="styles.css"/>
		</Head>
        <body>
          <Main />
          <NextScript />
          <script src="main.js" async={true}></script>
        </body>
      </Html>
    )
  }
}

export default MyDocument

```

To learn more about **Next.js** `_document.js`, you can check out the documentation [here](https://nextjs.org/docs/advanced-features/custom-document)