React renderToString()性能和缓存React组件

我注意到reactDOM.renderToString()方法开始显着减慢,当在服务器上渲染一个大的组件树。

背景

有点背景。该系统是一个完全同构的堆栈。最高级别的App组件呈现模板,页面,dom元素和更多组件。看看react代码,我发现它渲染〜1500组件(这包括任何简单的dom标签被视为一个简单的组件,< p>这是一个反应组件< / p&gt ;. 在开发中,渲染〜1500个组件需要约200-300ms。通过删除一些组件,我能够得到〜1200组件渲染在〜175-225毫秒。 在生产中,〜1500组件的renderToString需要大约50-200ms。 时间似乎是线性的。没有一个组件很慢,而是许多组件的总和。 问题 这在服务器上创建一些问题。冗长的方法导致服务器响应时间长。 TTFB比它应该高得多。使用api调用和业务逻辑,响应应为250ms,但使用一个250ms的renderToString它是双倍的!不好的SEO用户。此外,作为同步方法,renderToString()可以阻止节点服务器和备份后续请求(这可以通过使用2个单独的节点服务器来解决:1作为Web服务器,1作为一个服务单独渲染反应)。 尝试 理想情况下,renderToString在生产中需要5-50ms。我一直在努力的一些想法,但我不知道什么最好的方法是。 想法1:缓存组件 标记为“静态”的任何组件都可以缓存。通过保持带有渲染标记的缓存,renderToString()可以在渲染之前检查缓存。如果它找到一个组件,它会自动抓取该字符串。在高级组件执行此操作将保存所有嵌套的子组件的安装。您必须将缓存的组件标记的反应rootID替换为当前的rootID。 想法2:将组件标记为简单/愚钝 通过将组件定义为“简单”,反应应该能够在渲染时跳过所有生命周期方法。 React已经针对核心反应dom组件(< p />,< h1 />等)做到了这一点。将很好扩展自定义组件以使用相同的优化。

想法3:在服务器端渲染上跳过组件

不需要由服务器返回的组件(没有SEO值)可以在服务器上简单地跳过。一旦客户端加载,设置一个clientLoaded标志为true,并将其传递下来强制重新渲染。

关闭和其他尝试

到目前为止,我实现的唯一解决方案是减少在服务器上呈现的组件数量

我们正在寻找的一些项目包括

> React-dom-stream https://github.com/aickin/react-dom-stream(仍在为测试实现这一点)
> Babel内联元素https://babeljs.io/docs/plugins/transform-react-inline-elements/(似乎这是沿着想法2的线)

有人面临类似的问题吗?你能做什么?
谢谢。

使用react-router1.0和react0.14,我们错误地串行化我们的flux对象多次。

RoutingContext将为react-router路由中的每个模板调用createElement。这允许你注射任何你想要的道具。我们还使用助焊剂。我们发送一个大对象的序列化版本。在我们的例子中,我们在createElement中做flux.serialize()。串行化方法可能需要〜20ms。有4个模板,这将是额外的80ms到你的renderToString()方法

代码

function createElement(Component,props) {
    props = _.extend(props,{
        flux: flux,path: path,serializedFlux: flux.serialize();
    });
    return <Component {...props} />;
}
var start = Date.Now();
markup = renderToString(<RoutingContext {...renderProps} createElement={createElement} />);
console.log(Date.Now() - start);

轻松优化到:

var serializedFlux = flux.serialize(); // serialize one time only!

function createElement(Component,serializedFlux: serializedFlux
    });
    return <Component {...props} />;
}
var start = Date.Now();
markup = renderToString(<RoutingContext {...renderProps} createElement={createElement} />);
console.log(Date.Now() - start);

在我的情况下,这有助于减少renderToString()时间从〜120ms到〜30ms。 (你仍然需要添加1x serialize()的〜20ms的总数,这发生在renderToString()之前)这是一个很好的快速改进。 – 重要的是要记住要始终正确地做事情,即使你不知道立即的影响!

相关文章

一、前言 在组件方面react和Vue一样的,核心思想玩的就是组件...
前言: 前段时间学习完react后,刚好就接到公司一个react项目...
前言: 最近收到组长通知我们项目组后面新开的项目准备统一技...
react 中的高阶组件主要是对于 hooks 之前的类组件来说的,如...
我们上一节了解了组件的更新机制,但是只是停留在表层上,例...
我们上一节了解了 react 的虚拟 dom 的格式,如何把虚拟 dom...