As you can see in the below next.js code I am trying to defer load the render blocking css by giving my main.css file path in href attribute but I am struggling to do it in next.js. What I want is after loading the critical css in _document.js tag under tag, to load the non-critical css which is not above the fold.
_app.js
import App from "next/app"
import Head from "next/head"
import React from "react"
import { observer, Provider } from 'mobx-react'
import Layout from "../components/Layout"
import allStores from '../store'
export default class MyApp extends App {
componentDidMount = () => {
};
render() {
const { Component, pageProps, header, footer, } = this.props
return (
<>
<Head >
<link rel="preload" href="path/to/main.css" as="style"
onLoad="this.onload=null;this.rel='stylesheet'"></link>
</Head>
<Provider {...allStores}>
<Layout header={header} footer={footer}>
<Component {...pageProps} />
</Layout>
</Provider>
</>
)
}
}
Defer loading a CSS script gives you the ability to load CSS files after your web page (the DOM) has fully finished loading.
as @chrishrtmn said at _document.js you can do like this:
import Document, { Main, NextScript } from 'next/document'; import { CriticalCss } from '../components/CriticalCss'; class NextDocument extends Document { render() { return ( <html> <CriticalCssHead /> <body> <Main /> <NextScript /> </body> </html> ); } } export default NextDocument;
as in your component you can put the CSS:
import { readFileSync } from 'fs'; import { join } from 'path'; export interface Props { assetPrefix?: string; file: string; nonce?: string; } export const InlineStyle: React.FC<Props> = ({ assetPrefix, file, nonce }) => { const cssPath = join(process.cwd(), '.next', file); const cssSource = readFileSync(cssPath, 'utf-8'); const html = { __html: cssSource }; const id = `${assetPrefix}/_next/${file}`; return <style dangerouslySetInnerHTML={html} data-href={id} nonce={nonce} />; };
I got the source for this code from the current repo:
https://github.com/JamieMason/nextjs-typescript-tailwind-critical-css
have a look here
https://github.com/JamieMason/nextjs-typescript-tailwind-critical-css/tree/master/components/CriticalCssHead
Here's my current favorite solution, sourced from here: https://github.com/facebook/react/issues/12014#issuecomment-434534770
It results in two empty <script></script>
tags in your head, but works.
<script
dangerouslySetInnerHTML={{
__html: `</script><link rel='preload' href='style.css' as='style' onload="this.onload=null;this.rel='stylesheet'"/><script>`,
}}
/>
The Next.js team indicated that a similar strategy is possible with their component, but in practice, I was getting compilation errors: https://github.com/vercel/next.js/issues/8478#issuecomment-524332188
The error I received was:
Error: Can only set one of
children
orprops.dangerouslySetInnerHTML
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With