javascript - Preloading a .css file with NextJS - Stack Overflow

We are using NextJS and Material-UI for our site, and upon loading the pages, it gives a FOUC. I'v

We are using NextJS and Material-UI for our site, and upon loading the pages, it gives a FOUC. I've narrowed the problem down to the fact that the JS loads faster than the .css file, so I was wondering if there was a way to preload the .css file? All of our pages use the same .css file which is located under /pages/styles.css

Here is /pages/_app.js if that's any help:

// pages/_app.js
import { Provider } from 'next-auth/client'
import { createMuiTheme } from '@material-ui/core/styles';
import { ThemeProvider } from '@material-ui/styles';
import styles from './styles.css'

import Layout from '../ponents/layout'
import Head from 'next/head'

const theme = createMuiTheme({
  palette: {
    primary: {
      main: "#2196f3", // blue
    },
    secondary: {
      main: "#d3d3d3", // gray
    },
  },
});

export default function _App ({ Component, pageProps }) {
  return (
    <ThemeProvider theme={theme}>
      <Provider options={{ clientMaxAge: 0, keepAlive: 0 }} session={pageProps.session}>
        <Layout>  
          {/* Head */}
          <Head>
            <title>Kevin Support</title>
            <link rel="icon" href="/static/favicon.png"/>
          </Head>

          {/* Page */}
          <Component {...pageProps} />
        </Layout>
      </Provider>
    </ThemeProvider>
  )
}

We are using NextJS and Material-UI for our site, and upon loading the pages, it gives a FOUC. I've narrowed the problem down to the fact that the JS loads faster than the .css file, so I was wondering if there was a way to preload the .css file? All of our pages use the same .css file which is located under /pages/styles.css

Here is /pages/_app.js if that's any help:

// pages/_app.js
import { Provider } from 'next-auth/client'
import { createMuiTheme } from '@material-ui/core/styles';
import { ThemeProvider } from '@material-ui/styles';
import styles from './styles.css'

import Layout from '../ponents/layout'
import Head from 'next/head'

const theme = createMuiTheme({
  palette: {
    primary: {
      main: "#2196f3", // blue
    },
    secondary: {
      main: "#d3d3d3", // gray
    },
  },
});

export default function _App ({ Component, pageProps }) {
  return (
    <ThemeProvider theme={theme}>
      <Provider options={{ clientMaxAge: 0, keepAlive: 0 }} session={pageProps.session}>
        <Layout>  
          {/* Head */}
          <Head>
            <title>Kevin Support</title>
            <link rel="icon" href="/static/favicon.png"/>
          </Head>

          {/* Page */}
          <Component {...pageProps} />
        </Layout>
      </Provider>
    </ThemeProvider>
  )
}
Share Improve this question asked Mar 11, 2021 at 17:45 alexover1alexover1 811 gold badge1 silver badge4 bronze badges 3
  • Have you tried importing the styles directly from the node_modules? nextjs/docs/basic-features/… – Gh05d Commented Mar 11, 2021 at 21:26
  • The styles are ing from a file I have called styles.css, not node_modules – alexover1 Commented Mar 11, 2021 at 22:40
  • Does this stackoverflow./a/66089559/1870780 help answer your question? – juliomalves Commented Mar 13, 2021 at 12:41
Add a ment  | 

4 Answers 4

Reset to default 2

Perhaps styles weren't applied on the server-side. Try to add _document.js from Material-UI's Next.js example. Adjust it to your needs.

// pages/_document.js
import React from 'react';
import Document, { Html, Head, Main, NextScript } from 'next/document';
import { ServerStyleSheets } from '@material-ui/core/styles';
import theme from '../src/theme';

export default class MyDocument extends Document {
  render() {
    return (
      <Html lang="en">
        <Head>
          {/* PWA primary color */}
          <meta name="theme-color" content={theme.palette.primary.main} />
          <link
            rel="stylesheet"
            href="https://fonts.googleapis./css?family=Roboto:300,400,500,700&display=swap"
          />
        </Head>
        <body>
          <Main />
          <NextScript />
        </body>
      </Html>
    );
  }
}

// `getInitialProps` belongs to `_document` (instead of `_app`),
// it's patible with server-side generation (SSG).
MyDocument.getInitialProps = async (ctx) => {
  // Resolution order
  //
  // On the server:
  // 1. app.getInitialProps
  // 2. page.getInitialProps
  // 3. document.getInitialProps
  // 4. app.render
  // 5. page.render
  // 6. document.render
  //
  // On the server with error:
  // 1. document.getInitialProps
  // 2. app.render
  // 3. page.render
  // 4. document.render
  //
  // On the client
  // 1. app.getInitialProps
  // 2. page.getInitialProps
  // 3. app.render
  // 4. page.render

  // Render app and page and get the context of the page with collected side effects.
  const sheets = new ServerStyleSheets();
  const originalRenderPage = ctx.renderPage;

  ctx.renderPage = () =>
    originalRenderPage({
      enhanceApp: (App) => (props) => sheets.collect(<App {...props} />),
    });

  const initialProps = await Document.getInitialProps(ctx);

  return {
    ...initialProps,
    // Styles fragment is rendered after the app and page rendering finish.
    styles: [...React.Children.toArray(initialProps.styles), sheets.getStyleElement()],
  };
};

Also, you can try to remove server-side injected CSS in the _app.js like so (see example):

React.useEffect(() => {
    // Remove the server-side injected CSS.
    const jssStyles = document.querySelector('#jss-server-side');
    if (jssStyles) {
      jssStyles.parentElement.removeChild(jssStyles);
    }
  }, []);

I faced this same issue. what I did was to make this work was to add this script inside _document.tsx

     <script
            dangerouslySetInnerHTML={{
              __html: `
              if(document) {
            document.querySelectorAll("link[rel='preload'][as='style']").forEach(link => link.rel = "stylesheet")}
            `
            }}
          />

You could always use a display: none; on the body element until the style sheet has loaded then display: block;

Load the CSS file with the <link> element inside the head. The parsing process of the browser will then make sure that the CSS file is loaded before the site content is shown.

In your current approach you load the CSS is loaded with JavaScript, after the FCP has rendered the CSS will be parsed.

You have 2 options to fix this:

  1. You link the CSS file as mentioned above with a <link> element.
  2. You get the text content of the CSS file and set it as the innerHTML of a <style> element.

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744407807a4572719.html

相关推荐

  • javascript - Preloading a .css file with NextJS - Stack Overflow

    We are using NextJS and Material-UI for our site, and upon loading the pages, it gives a FOUC. I'v

    6天前
    40

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信