React与Express的服务器端渲染 - 客户端检验和样式警告

3

我对React服务器端渲染还不太熟悉,在使用React、Redux、React Router和Material UI开发小型演示时,遇到了以下问题:不确定同构样式和资源是如何与Webpack一起工作的。

请您纠正我如果以下管道的服务器端渲染工作方式有误:

  • 使用renderToString将React组件解析为HTML。
  • 在客户端上呈现HTML后,所有事件和样式都被附加,这意味着React会尝试在客户端上再次呈现组件,如果组件已经创建,则会再次创建它。
  • 检查和判断组件是否已经创建是基于校验和的。

请参阅Git中报告的问题 https://github.com/callemall/material-ui/issues/4466

代码 https://github.com/sabha/React-Redux-Router-MaterialUI-ServerSideRendering

'warning.js:44Warning: React attempted to reuse markup in a container but the checksum was invalid. This generally means that you are using server rendering and the markup generated on the server was not what the client was expecting. React injected new markup to compensate which works but you have lost many of the benefits of server rendering. Instead, figure out why the markup being generated is different on the client or server: (client) 0;text-align:center;mui-prepared:;-webki (server) 0;text-align:center;-webkit-user-select:'


1
你可能想看一下这篇文章 - https://www.garysieling.com/blog/fixing-react-attempted-reuse-markup-container-checksum-invalid - R.R
1
有一个小的解决方法 https://github.com/Hashnode/mern-starter/issues/149 - Alfred Crosby
3个回答

4
在这个 Razzle Material UI Styled Example 项目中,我是通过以下方式设置用户代理的: server.js:
renderToString(<Application userAgent={request.headers['user-agent']} />)

client.js:

hydrate(<Application userAgent={navigator.userAgent} />, document.getElementById('root'))

Main.js:

class Main extends Component {
    constructor(properties, context) {
        super(properties, context)

        this.muiTheme = getMuiTheme({
            userAgent: properties.userAgent
        })
    }

    render() {
        return (
            <MuiThemeProvider muiTheme={this.muiTheme}></MuiThemeProvider>
        )
    }
}

它运行良好,我认为它也是正确的。


1

(客户端) 0;text-align:center;mui-prepared:;-webkit
(服务器) 0;text-align:center;-webkit-user-select:

您会注意到两者之间的区别在于多了一个未出现在服务器渲染中的 mui-prepared。在文档的服务器渲染指南底部有关于此的注释。

为了确保我们的样式转换仅被应用一次,当 process.env.NODE_ENV !== 'production' 时,我们会向每个样式添加一个额外属性。

看起来您只在服务器上设置了 process.env.NODE_ENV=production(这是我的情况)。


嗨,我在运行Racket样板时遇到了这个错误,在开发环境中,我应该更改process.env还是这个错误将在生产环境中消失。谢谢。 - Okura
@Matt Cole 将 NODE_ENV 设置为 production 会在各个地方完全改变事情。 - CESCO

1

Material-UI采用内联样式方法来为元素添加样式,这在服务器端渲染时会遇到一个问题:

在客户端,Material-UI只会添加特定于运行应用程序的浏览器的内联样式。但是在服务器上,您不在浏览器中,因此如何知道使用哪些特定的样式规则,以使呈现的HTML与客户端呈现的HTML匹配并避免React警告?

他们在文档中介绍了如何解决这个问题。基本上,这意味着在进行服务器端渲染之前,确保设置用户代理字符串(从HTTP请求头中捕获)。

这是他们的服务器端渲染文档中的内容:

import getMuiTheme from 'material-ui/getMuiTheme';
import MuiThemeProvider from 'material-ui/MuiThemeProvider';
import {green100, green500, green700} from 'material-ui/styles/colors';

const muiTheme = getMuiTheme({
  palette: {
    primary1Color: green500,
    primary2Color: green700,
    primary3Color: green100,
  },
}, {
  avatar: {
    borderColor: null,
  },
  userAgent: req.headers['user-agent'],
});

class Main extends React.Component {
  render() {
    return (
      <MuiThemeProvider muiTheme={muiTheme}>
        <div>Hello world</div>
      </MuiThemeProvider>
    );
  }
}

谢谢@Brandon。在我的server.js文件中,我正在传递用户代理,该代理是我从Express请求头中接收到的,如下所示:const muiTheme = getMuiTheme({userAgent: req.headers['user-agent']}); - Sabha B

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