在使用NextJS/React和@material-ui/core时出现FOUC问题

4
我的简单NextJS页面长这样(结果可以在https://www.schandillia.com/中查看):
/* eslint-disable no-unused-vars */

import React, { PureComponent, Fragment } from 'react';
import Head from 'next/head';
import compose from 'recompose/compose';
import Layout from '../components/Layout';
import { withStyles } from '@material-ui/core/styles';
import Button from '@material-ui/core/Button';

const styles = {
  root: {
    textAlign: 'center',
    paddingTop: 200,
  },
  p: {
    textTransform: 'uppercase',
    color: 'red',
  },
};

class Index extends PureComponent {
  render() {
    const { classes } = this.props;
    const title = 'Project Proost';
    const description = 'This is the description for the homepage';
    return (
      <Fragment>
        <Head>
          <title>{ title }</title>
          <meta name="description" content={description} key="description" />
        </Head>
        <Layout>
          <p className={classes.p}>amit</p>
          <Button variant="contained" color="secondary">
            Secondary
          </Button>
        </Layout>
      </Fragment>
    );
  }
}

export default withStyles(styles)(Index);

我正在导入一堆组件,使用@material-ui/core库为我的项目进行样式设置。同时我也有一个本地的样式定义被分配给了一个style常量。

这里发生的问题似乎是我的样式没有在服务器上渲染,这就是为什么在加载时提供的文件没有样式的原因。然后CSS由客户端代码呈现。结果就是会有一闪而过的未经样式处理的内容,持续时间差不多一秒钟,足够引起注意。

有没有解决这个问题的方法?整个代码库可以在https://github.com/amitschandillia/proost/tree/master/web中参考。


如果您在应用程序加载时观察元素检查器,可以看到它正在将MUI样式标签注入<head>中。我建议尝试调整MUI使用JSS的配置。这是MUI文档中有趣的信息页面,特定部分开始提供有关调整此性能方面的建议:https://material-ui.com/customization/css-in-js/#html-comment - BugsArePeopleToo
我知道我的样式被注入到<head>部分。但我的问题是这种注入只发生在客户端而不是服务器端。这就是导致FOUC的原因。我需要一些方法来确保样式信息在页面推送之前在服务器端被注入。 - TheLearner
不,我正在从头开始使用NextJS构建。 - TheLearner
如果您不会对生产构建进行任何其他配置,并且使用react-create-app创建了应用程序,我建议使用react-create-appreact-scripts build。 我曾经花费了相当多的时间为此配置webpack,然后发现它已经默认附带了一个简单但有用的构建工具。 - Pedro Vieira
2个回答

2

当我试图制作一个使用material-ui的应用程序的生产版本时,我遇到了类似的问题。我通过添加一个JSS提供者来解决它,就像这样:


import JssProvider from "react-jss/lib/JssProvider";

class App extends Component {
  render() {
    <JssProvider>
      *the rest of your material-ui components*
    </JssProvider>
  }
}

你必须在每个页面都这样做吗?还是我只需要在_document.jsx中用<JssProvider />包装我的<Main />和<NextScript />元素一次,然后在每个单独的页面(Index.jsx、About.jsx等)中忘记它? - TheLearner
1
我有很多组件只加载在两个主要组件中,就像你一样。所以我只在这些主要组件上使用它。我认为如果你所有的组件都被引用在<Main /><NextScript />中,那么只需关注它们并忘记单独的组件即可。至少这对我起作用了。 - Pedro Vieira
1
好的,我现在看了你的代码,在你的情况下,你在同一个 RootDocument 组件上使用它们。你可以将 <JSSProvider> 包装在 <Html lang="en"> 上,甚至是在 RootDocument 组件内部,如果你在那里使用更多的 material-ui 样式化组件。 - Pedro Vieira

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接