next.js - nextjs - 页面样式最初未加载,导致巨大的图标和损坏的 CSS

标签 next.js material-ui

我有一个页面,在页面加载时显示巨大的图标和几乎损坏的 css。遵循官方 nextjs mui5 示例。

    "next": "^12.3.1",
 "react": "^18.2.0",
"@emotion/react": "^11.10.4",
"@emotion/server": "^11.10.0",
"@emotion/styled": "^11.10.4",
"@mui/icons-material": "^5.10.6",
"@mui/lab": "^5.0.0-alpha.102",
"@mui/material": "^5.10.8",
"@mui/styles": "^5.10.8",

Live demo of the issue - https://wedpicker.com/

下面是我的代码

应用程序

import React from 'react';
import PropTypes from 'prop-types';
import Head from 'next/head';
import { CacheProvider } from '@emotion/react';
import CssBaseline from '@mui/material/CssBaseline';
import Layout from '../components/layout';
import { useState, useEffect } from 'react';
import { useRouter } from 'next/router';
import LinearProgress from '@mui/material/LinearProgress';
import * as gtag from '../lib/googleAnalytics';
import '../styles/globals.css';
import createEmotionCache from '../components/theme/createEmotionCache';

// Client-side cache, shared for the whole session of the user in the browser.
const clientSideEmotionCache = createEmotionCache();

export default function NCD(props) {
  const { Component, emotionCache = clientSideEmotionCache, pageProps } = props;
  const [isLoading, setLoadingState] = useState(false);

  const router = useRouter();

  useEffect(() => {
    const handleRouteChange = (url) => {
      gtag.pageview(url)
    }
    // Logging to prove _app.js only mounts once,
    // but initializing router events here will also accomplishes
    // goal of setting state on route change
    router.events.on('routeChangeStart', () => {
      setLoadingState(true);
    });

    router.events.on('routeChangeComplete', () => {
      handleRouteChange;
      setLoadingState(false);
    });

    router.events.on('routeChangeError', () => {
      setLoadingState(false);
    });

    if (typeof window == 'undefined') {
      setLoadingState(true);
    }

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

  return (
    <React.Fragment>
      <Head>
        <title>{process.env.SITENAME}</title>
        <meta name="viewport" content="initial-scale=1, width=device-width" />
      </Head>
      <CacheProvider value={emotionCache}>
      {/* CssBaseline kickstart an elegant, consistent, and simple baseline to build upon. */}
      <CssBaseline />
        <Layout>
      {isLoading? (  
        <>
          <div className="pageLoader">
            <LinearProgress />
          </div>
         </>):(
          <>

          <Component {...pageProps} />
        
         </>
        )}
        </Layout>
        </CacheProvider>
    </React.Fragment>
  );
}

NCD.propTypes = {
  Component: PropTypes.elementType.isRequired,
  pageProps: PropTypes.object.isRequired,
};

文档.js


import * as React from 'react';
import Document, { Html, Head, Main, NextScript } from 'next/document';
import createEmotionServer from '@emotion/server/create-instance';
import createEmotionCache from '../components/theme/createEmotionCache';
import { GA_TRACKING_ID } from '../lib/googleAnalytics';
import ServerStyleSheets from '@mui/styles/ServerStyleSheets';

export default class MyDocument extends Document {
  render() {
    return (
      <Html lang='en'>
        <Head>

          <link rel="shortcut icon" href="/favicon.ico" />
          <link
            rel="stylesheet"
            href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap"
          />
          {/* Global Site Tag (gtag.js) - Google Analytics */}
          <script
            async
            src={`https://www.googletagmanager.com/gtag/js?id=${GA_TRACKING_ID}`}
          />
          <script
            dangerouslySetInnerHTML={{
              __html: `
            window.dataLayer = window.dataLayer || [];
            function gtag(){dataLayer.push(arguments);}
            gtag('js', new Date());
            gtag('config', '${GA_TRACKING_ID}', {
              page_path: window.location.pathname,
            });
          `,
            }}
          />

        </Head>
        <body>
          <Main />
          <NextScript />
        </body>
      </Html>
    )
  }
}

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

  const originalRenderPage = ctx.renderPage;

  // You can consider sharing the same Emotion cache between all the SSR requests to speed up performance.
  // However, be aware that it can have global side effects.
  const cache = createEmotionCache();
  const { extractCriticalToChunks } = createEmotionServer(cache);

  const sheets = new ServerStyleSheets()

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

  const initialProps = await Document.getInitialProps(ctx);
  // This is important. It prevents Emotion to render invalid HTML.
  // See https://github.com/mui/material-ui/issues/26561#issuecomment-855286153
  const emotionStyles = extractCriticalToChunks(initialProps.html);
  const emotionStyleTags = emotionStyles.styles.map((style) => (
    <style
      data-emotion={`${style.key} ${style.ids.join(' ')}`}
      key={style.key}
      // eslint-disable-next-line react/no-danger
      dangerouslySetInnerHTML={{ __html: style.css }}
    />
  ));

  return {
    ...initialProps,
    emotionStyleTags,
  };
};

布局.js


import { ThemeProvider, StyledEngineProvider } from '@mui/material/styles';
import CssBaseline from '@mui/material/CssBaseline';
import {lightTheme, darkTheme} from '../components/theme';
import TopAppBar from './ui/topAppBar';
import { useCookies } from 'react-cookie';
import Copyright from '../components/ui/copyright';
import Box from '@mui/material/Box';

const layout = ({ children }) => {
  const [cookies, setCookie] = useCookies(['darkTheme']);

  return <>
    <StyledEngineProvider injectFirst>
      <ThemeProvider theme={cookies.darkTheme=="true" ? darkTheme : lightTheme}>
        <CssBaseline />
      
        <header>
          <nav>
          <TopAppBar />
          </nav>
        </header>

          <main>{children}</main>
      <Box mt={8} mb={4} >
        <Copyright />
      </Box>
      </ThemeProvider>
    </StyledEngineProvider>
  </>;
};

export default layout;

最佳答案

我在 next-js 和 mui 组合上挣扎了一段时间。您可以更新以下内容:

  • 将 nextjs 更新到最新版本。
  • 关注this示例(再次检查您是否拥有此处的所有代码,包括 createEmotionCache ,看到您在组件下有它,但不确定它是否相同)。
  • 删除 <StyledEngineProvider injectFirst> ,这就是为我固定风格的东西。
  • 使用Image来自next/image而不是<img>图像元素。
  • 您不需要在 Layout.js 中导入任何 mui。删除 StyledEngineProvider、ThemeProvider。

关于next.js - nextjs - 页面样式最初未加载,导致巨大的图标和损坏的 CSS,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74046880/

相关文章:

javascript - Next.js 按需静态再生

Azure Frontdoor 多路径路由不适用于存储静态 Web 应用程序

javascript - Next.js 表单可以在本地运行,但不能在实时服务器上运行

javascript - 如何在React Web中处理长按事件

javascript - 直接访问 url 时如何修复 "Cannot read property ' 文档' of undefined"?Next.js 和 apexcharts lib

javascript - 部署到AWS后无法通过Next.Js中的getInitialProps获取数据,但可以在开发环境中使用

javascript - 在 Material ui usestyles 中使用同级组合器

javascript - Material-UI - 如何更改深色主题的默认颜色?

html - 设置 MUI 选择宽度?

redux - 无法在嵌套在对话框中的连接组件中找到 "store"错误