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, 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.
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:
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.
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
Top comments (0)