在同构React Web应用程序中有选择地进行服务器渲染的最佳方法是什么?

时间:2015-02-14 03:25:26

标签: javascript reactjs isomorphism isomorphic-javascript

我希望拥有大量内容的网页获得最佳性能。特别感兴趣的是,在移动设备上,我希望用户尽快看到首屏内容,然后让应用程序尽快进行自举。

我的变量isBrowser在浏览器环境中为true,但在服务器环境中为false。考虑以下渲染函数:

render() {
  return (
    <div>
      <ContentAboveTheFold />
      { isBrowser && <ContentBelowTheFold /> }
    </div>
  )
}

请注意,通过以这种方式构造render(),服务器的渲染标记较少,通过网络传输的数据较少,并且浏览器在首次通过时渲染的标记较少。

这很好用,但在控制台React警告

  

React尝试在容器中使用重用标记,但校验和无效。这通常意味着您正在使用服务器呈现,并且在服务器上生成的标记不是客户端所期望的。 React注入了新的标记以补偿哪些有效但你已经失去了服务器渲染的许多好处。相反,弄清楚为什么生成的标记在客户端或服务器上是不同的。

在服务器上,React使用在顶级元素中嵌入的校验和(对于ex data-react-checksum="941190765")呈现标记。然后在客户端上,react会在第一次呈现后计算校验和,如果它与服务器的校验和不同,它会完全丢弃服务器生成的标记,并将其替换为客户端生成的标记。

作为一种解决方法,我发现在我的顶级组件的componentDidMount生命周期方法中,我可以在下一个动画帧上安排以下操作:

componentDidMount() {
  requestAnimationFrame(() => {
    appIsMounted = true;
    this.forceUpdate();
  });
}

然后我可以像这样编写我的渲染方法,并且反应没有产生关于校验和的任何警告:

render() {
  return (
    <div>
      <ContentAboveTheFold />
      { appIsMounted && <ContentBelowTheFold /> }
    </div>
  )
}

这样做有没有明显的性能优势?在任何一种情况下,折叠以上的内容都会显得同样快,对吧?额外的复杂性是否合理?

1 个答案:

答案 0 :(得分:4)

是的,使用requestAnimationFrame / setTimeout进行更新是正确的方法。

我会把它放在状态,而不是使用变量和forceUpdate。