使用 Express 响应服务器端渲染 - 客户端校验和和样式警告

React Server side rendering with Express - warning on the client checksum & Styling

我是 React 服务器端渲染的新手,正在使用 React , Redux , React router , Material UI 进行一个小型演示。我面临的问题是以下警告。不确定同构样式和资产如何与 webpack 一起使用。

我了解服务器端渲染的管道是如何工作的,如果有错请指正。

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:'

Material-UI 以其 inline-style 样式化元素的方法,在 server-side 渲染方面存在以下问题:

在客户端,MaterialUI 渲染仅添加特定于 运行 应用程序浏览器的内联样式。但是在服务器上,您不在浏览器中,因此如何知道要使用 哪个 特定样式规则,以便呈现的 HTML 与 client-rendered HTML 并避免 React 警告?

他们有关于如何解决问题的文档。从本质上讲,这意味着确保在进行服务器端呈现之前设置用户代理字符串(从 HTTP 请求 Header 中捕获)。

这是他们的 serverside rendering documentation:

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>
    );
  }
}

(client) 0;text-align:center;mui-prepared:;-webki
(server) 0;text-align:center;-webkit-user-select:

您会注意到两者之间的区别是服务器渲染中不存在的额外 mui-prepared。在文档的 server rendering guide 底部有关于此的注释。

In order to make sure our style transformations are only applied once, we add an additional property to each style when process.env.NODE_ENV !== 'production'.

看起来您只有 process.env.NODE_ENV=production 在服务器上(我就是这种情况)。

在这个 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>
        )
    }
}

效果很好,我也觉得很对。