我注意到reactDOM.renderToString()
在服务器上渲染大型组件树时,该方法开始显着减慢速度。
背景
有点背景。该系统是完全同构的堆栈。最高级别的App
组件呈现模板,页面,dom元素和更多组件。查看一下react代码,我发现它呈现了约1500个组件(这包括任何被视为简单组件的简单dom标签<p>this is a react component</p>
。
在开发中,渲染〜1500个组件大约需要200-300ms。通过删除一些组件,我能够在约175-225毫秒内获得约1200个组件进行渲染。
在生产中,大约1500个组件上的renderToString大约需要50-200ms。
时间确实是线性的。没有任何一个要素是缓慢的,而是许多要素的总和。
问题
这在服务器上产生了一些问题。冗长的方法导致服务器响应时间长。TTFB比应有的要高得多。使用api调用和业务逻辑,响应应该为250毫秒,但是使用250毫秒的renderToString时,响应会加倍!对SEO和用户不利。同样,作为一种同步方法,它renderToString()
可以阻止节点服务器并备份后续请求(这可以通过使用2个单独的节点服务器来解决:1个作为Web服务器,而1个作为仅提供反应的服务)。
尝试次数
理想情况下,生产中的renderToString需要5到50毫秒。我一直在研究一些想法,但是我不确定最好的方法是什么。
想法1:缓存组件
任何标记为“静态”的组件都可以缓存。通过保留具有渲染标记renderToString()
的缓存,可以在渲染之前检查缓存。如果找到一个组件,它将自动获取字符串。在较高级别的组件上执行此操作将节省所有嵌套子组件的安装。您将不得不用当前的rootID替换缓存的组件标记的react rootID。
理念2:将组件标记为简单/哑巴
通过将组件定义为“简单”,react应该能够在渲染时跳过所有生命周期方法。反应已经这样做了芯反应,DOM组件(<p/>
,<h1/>
,等)。扩展自定义组件以使用相同的优化会很好。
理念3:跳过服务器端渲染上的组件
Components that do not need to be returned by the server (no SEO value) could simply be skipped on the server. Once the client loads, set a clientLoaded
flag to true
and pass it down to enforce a re-render.
Closing and other attempts
The only solution I've implemented thus far is to reduce the number of components that are rendered on the server.
Some projects we're looking at include:
- React-dom-stream (still working on implementing this for a test)
- Babel inline elements (seems like this is along the lines of Idea 2)
Has anybody faced similar issues? What have you been able to do? Thanks.
使用react-router1.0和react0.14,我们错误地多次序列化了我们的flux对象。
RoutingContext
将要求createElement
您的react-router路由中的每个模板。这使您可以注入所需的任何道具。我们也使用通量。我们发送大对象的序列化版本。在我们的例子中,我们flux.serialize()
在createElement中进行。序列化方法可能需要20毫秒左右的时间。如果有4个模板,那将比您的renderToString()
方法多花80毫秒!旧代码:
轻松优化为此:
就我而言,这有助于将
renderToString()
时间从〜120ms 减少到〜30ms。(您仍然需要将1xserialize()
的〜20ms加到总数上,这要在之前完成renderToString()
)这是一个不错的快速改进。-重要的是要记住,即使您不知道直接的影响,也要始终正确地做事!