【问题标题】:Server Side Rendering React服务器端渲染反应
【发布时间】:2017-01-14 03:18:07
【问题描述】:

一段时间以来,我一直在尝试为 Redux/React 应用程序实现服务器端渲染。我已经根据我遵循的示例设置了所有内容,但是发生了一些奇怪的事情。

当我查看 Google Chrome 时间轴中的渲染过程时,我注意到我的 html 出现了一瞬间,然后它消失了,然后它再次从头开始渲染所有内容(有点像在 React 时它忽略了我的服务器端内容尝试安装到它,然后只使用正常的客户端渲染)。

我检查了发送给客户端的内容,似乎没问题。分配给窗口的所有 html、head 标记和 javascript 都在那里。此外,当它最初尝试从服务器端渲染 html 时,它看起来很好(我检查了 Chrome 时间轴并逐帧查看了它正在渲染的图像)。

我想知道从以下设置中是否可以立即看出任何事情,或者有什么想法可能会发生什么。以下是显示我实现的伪代码。如果任何 cmets 需要更多代码或信息,我会进行编辑。

// client - configureStore and configureRoutes are custom 
// functions that just return the store with initial state and the routes.
const serverState = JSON.parse(window._SERVERSTATE);
const store = configureStore(browserHistory, serverState);
const history = syncHistoryWithStore(browserHistory, store);
const routes = configureRoutes(store);

render(
    <Provider store={store}>
        <Router history={history} routes={routes}/>
    </Provider>,
    document.getElementById('main')
);

// server - node.js
const initialState = setupState();
const memoryHistory = createMemoryHistory(req.url);
const store = configureStore(memoryHistory, initialState);
const history = syncHistoryWithStore(memoryHistory, store);
const routes = configureRoutes(store);

match({ history, routes, location: req.url }, (err, redirectLocation, renderProps) => {

    if (err) {
        return next(err)
    }

    if (redirectLocation) {
        return res.redirect(302, redirectLocation.pathname + redirectLocation.search)
    }

    // Fetches all data need to render components by calling their static initializeActions functions
    fetchData(store.dispatch, renderProps.components, renderProps.params)
        .then(() => {

            const body = renderToString(
                <Provider store={store}>
                    <RouterContext {...renderProps} />
                </Provider>
            );

            const helmetHeaders = Helmet.rewind();

            const state = JSON.stringify(store.getState());

            const html = `
                <!DOCTYPE html>
                <html>
                    <head>
                        ${helmetHeaders.title.toString()}
                        <link rel="stylesheet" type="text/css" href="/styles.css">
                    </head>
                    <body>
                        <div id="main">
                            ${body}
                        </div>
                        <script> 
                            window._SERVERSTATE = ${JSON.stringify(state)}
                        </script>
                        <script src="/app.js"></script>
                    </body>
                </html>
        })
})

// Typical component
class Example extends React.Component{
    static initializeActions = [ ExampleAction ]

    render() {
        <div>Hello</div>
    }
}

【问题讨论】:

  • 你是问重新渲染过程是否正常?因为——信不信由你——客户端重新渲染从服务器发送的所有内容实际上是正常的,尽管有一些您几乎不必担心的优化。然而,不正常的可能是 React 的 DOM diffing 没有启动,而是进行了重绘,而不是只更新不同的部分(例如,几乎什么都没有,因为没有太多需要重绘)。
  • @SalehenRahman 我正在询问有关如何解决 React 重绘所有看起来非常不正常的问题的提示。感觉 React 不知何故没有正确找到服务器端渲染的内容。并且只是覆盖
    中的所有内容,但我不能确定。并且没有错误消息:(

标签: reactjs redux react-router react-redux react-router-redux


【解决方案1】:

如果您的客户端代码再次渲染,这意味着您的服务器渲染与客户端渲染不同,因此您的客户端代码只需清除所有内容并重新渲染即可。

这就是我要做的,只需使用您本地的bundle.js 替换您的bundle.min.js 来调试您的应用程序,您应该会找到关于react markup checksum 的警告,并且只需比较您的服务器渲染和客户端渲染的内容,看看有什么区别。

我的问题是我的服务器上有data-react-id 属性。所以我用ReactDom.renderToStaticMarkup 代替ReactDom.renderToString。你可以先试试。

【讨论】:

  • 嘿@chenkehxx 我终于弄清楚出了什么问题。我正在使用异步路由,并且要使客户端与渲染一起工作,您需要先调用 match。
【解决方案2】:

我终于知道出了什么问题。如果你在 require.ensure 中使用异步路由,那么你必须在渲染客户端之前调用 match:

match({ history, routes }, (err, redirectLocation, renderProps) => {
    render(
        <Provider store={store}>
            <Router history={history} routes={routes}/>
        </Provider>,
        document.getElementById('main')
    );
});

【讨论】:

    【解决方案3】:

    我已经为反应服务器端渲染创建了启动器。它是使用来自 redux 和 react-router v4 的建议构建的。请检查一下

    https://github.com/gzoreslav/react-redux-saga-universal-application

    【讨论】:

      猜你喜欢
      • 2015-05-09
      • 2017-12-29
      • 2019-02-09
      • 2020-04-19
      • 2018-10-02
      • 1970-01-01
      • 1970-01-01
      • 2020-06-27
      • 2016-10-08
      相关资源
      最近更新 更多