【问题标题】:Preloading a .css file with NextJS使用 NextJS 预加载 .css 文件
【发布时间】:2021-06-09 18:07:40
【问题描述】:

我们的网站使用 NextJS 和 Material-UI,在加载页面时,它会给出一个 FOUC。我已将问题缩小到 JS 加载速度比 .css 文件快的事实,所以我想知道是否有办法预加载 .css 文件?我们所有的页面都使用位于/pages/styles.css下的同一个.css文件

这里是/pages/_app.js,如果有帮助的话:

// 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 '../components/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>
  )
}

【问题讨论】:

标签: javascript html css next.js


【解决方案1】:

也许样式没有应用到服务器端。尝试从 Material-UI 的 Next.js example 添加_document.js。根据您的需要进行调整。

// 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.com/css?family=Roboto:300,400,500,700&display=swap"
          />
        </Head>
        <body>
          <Main />
          <NextScript />
        </body>
      </Html>
    );
  }
}

// `getInitialProps` belongs to `_document` (instead of `_app`),
// it's compatible 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()],
  };
};

此外,您可以尝试在_app.js 中删除服务器端注入的 CSS,如下所示(请参阅example):

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

【讨论】:

    【解决方案2】:

    加载带有 &lt;link&gt; 元素的 CSS 文件。浏览器的解析过程将确保在显示网站内容之前加载 CSS 文件。

    在您当前的方法中,您加载的 CSS 是用 JavaScript 加载的,在 FCP 呈现之后,CSS 将被解析。

    您有 2 个选项来解决此问题:

    1. 您使用&lt;link&gt; 元素链接上述CSS 文件。
    2. 您获取 CSS 文件的文本内容并将其设置为 &lt;style&gt; 元素的 innerHTML

    【讨论】:

    • 如何将 .css 文件与 &lt;link&gt; 元素链接?我试过&lt;link rel="stylesheet" href="/pages/styles.css"/&gt;,它仍然在页面加载时闪烁
    猜你喜欢
    • 2023-01-26
    • 1970-01-01
    • 2022-10-18
    • 2021-04-25
    • 2020-11-01
    • 2022-08-19
    • 1970-01-01
    • 2021-06-10
    • 2021-09-12
    相关资源
    最近更新 更多