的 更新1 强> :我在底部添加了一个完整的工作示例。它将组件缓存在内存和更新中 data-reactid 。
data-reactid
这实际上可以很容易地完成。你应该 猴补丁 ReactCompositeComponent 并检查缓存版本:
ReactCompositeComponent
import ReactCompositeComponent from 'react/lib/ReactCompositeComponent'; const originalMountComponent = ReactCompositeComponent.Mixin.mountComponent; ReactCompositeComponent.Mixin.mountComponent = function() { if (hasCachedVersion(this)) return cache; return originalMountComponent.apply(this, arguments) }
你应该在你面前这样做 require('react') 您应用中的任何位置。
require('react')
的 Webpack说明: 强> 如果你使用类似的东西 new webpack.ProvidePlugin({'React': 'react'}) 你应该把它改成 new webpack.ProvidePlugin({'React': 'react-override'}) 在哪里进行修改 react-override.js 和出口 react (即 module.exports = require('react') )
new webpack.ProvidePlugin({'React': 'react'})
new webpack.ProvidePlugin({'React': 'react-override'})
react-override.js
react
module.exports = require('react')
一个在内存和更新中缓存的完整示例 reactid 属性可能是这样的:
reactid
import ReactCompositeComponent from 'react/lib/ReactCompositeComponent'; import jsan from 'jsan'; import Logo from './logo.svg'; const cachable = [Logo]; const cache = {}; function splitMarkup(markup) { var markupParts = []; var reactIdPos = -1; var endPos, startPos = 0; while ((reactIdPos = markup.indexOf('reactid="', reactIdPos + 1)) != -1) { endPos = reactIdPos + 9; markupParts.push(markup.substring(startPos, endPos)) startPos = markup.indexOf('"', endPos); } markupParts.push(markup.substring(startPos)) return markupParts; } function refreshMarkup(markup, hostContainerInfo) { var refreshedMarkup = ''; var reactid; var reactIdSlotCount = markup.length - 1; for (var i = 0; i <= reactIdSlotCount; i++) { reactid = i != reactIdSlotCount ? hostContainerInfo._idCounter++ : ''; refreshedMarkup += markup[i] + reactid } return refreshedMarkup; } const originalMountComponent = ReactCompositeComponent.Mixin.mountComponent; ReactCompositeComponent.Mixin.mountComponent = function (renderedElement, hostParent, hostContainerInfo, transaction, context) { return originalMountComponent.apply(this, arguments); var el = this._currentElement; var elType = el.type; var markup; if (cachable.indexOf(elType) > -1) { var publicProps = el.props; var id = elType.name + ':' + jsan.stringify(publicProps); markup = cache[id]; if (markup) { return refreshMarkup(markup, hostContainerInfo) } else { markup = originalMountComponent.apply(this, arguments); cache[id] = splitMarkup(markup); } } else { markup = originalMountComponent.apply(this, arguments) } return markup; } module.exports = require('react');
它不完整的解决方案 我有同样的问题,我的反应同构应用程序,我使用了几件事。
1)在nodejs服务器前使用Nginx,并在短时间内缓存渲染的响应。
2)在显示项目列表的情况下,我仅使用列表的子集。例如,我将仅渲染X项以填充视口,并使用Websocket或XHR在客户端加载列表的其余部分。
3)我的一些组件在服务器端呈现中是空的,只会从客户端代码(componentDidMount)加载。 这些组件通常是图形或配置文件相关的组件。这些组件通常在SEO的观点上没有任何好处
4)关于SEO,从我的经验6个月与同构应用程序。 Google Bot可以轻松读取客户端React Web页面,因此我不确定为什么我们会厌烦服务器端渲染。
5)保持 <Head > 和 <Footer> 作为静态字符串或使用模板引擎( Reactjs-handellbars ),并只渲染页面的内容,(它应该保存一些渲染组件)。 如果是单页应用,您可以更新每个导航内的标题说明 Router.Run 。
<Head >
<Footer>
Router.Run
我认为 快速反应的渲染 可以帮助你。它可以将服务器渲染性能提高三倍。
为了尝试它,您只需要安装包并将ReactDOM.renderToString替换为FastReactRender.elementToString:
var ReactRender = require('fast-react-render'); var element = React.createElement(Component, {property: 'value'}); console.log(ReactRender.elementToString(element, {context: {}}));
你也可以使用 快速反应服务器 在这种情况下,渲染速度将是传统反应渲染速度的14倍。但是,为此,必须使用它来声明要呈现的每个组件(请参阅fast-react-seed中的示例,如何为webpack执行此操作)。