标签: isomorphic-javascript

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

我注意到reactDOM.renderToString()在服务器上渲染大型组件树时,该方法开始显着减慢.

背景

一点背景.该系统是一个完全同构的堆栈.最高级别的App组件呈现模板,页面,dom元素和更多组件.查看反应代码,我发现它渲染了~1500个组件(这包括任何简单的dom标记,它被视为一个简单的组件,<p>this is a react component</p>.

在开发中,渲染~1500个组件需要大约200-300ms.通过删除一些组件,我能够在~175-225ms内获得~1200个组件.

在生产中,〜1500个组件上的renderToString大约需要50-200ms.

时间似乎是线性的.没有一个组件是慢的,而是它的总和.

问题

这会在服务器上产生一些问题.冗长的方法导致服务器响应时间过长.TTFB比它应该高很多.使用api调用和业务逻辑,响应应该是250ms,但是使用250ms renderToString它会加倍!SEO和用户不好.此外,作为同步方法,renderToString()可以阻止节点服务器并备份后续请求(这可以通过使用2个单独的节点服务器来解决:1作为Web服务器,1作为服务来单独呈现反应).

尝试

理想情况下,生产中需要5-50ms的renderToString.我一直在研究一些想法,但我不确定最好的方法是什么.

想法1:缓存组件

任何标记为"静态"的组件都可以缓存.通过使用呈现的标记保持缓存,renderToString()可以在呈现之前检查缓存.如果找到一个组件,它会自动抓取该字符串.在高级组件中执行此操作将保存所有嵌套子组件的安装.您必须使用当前的rootID替换缓存的组件标记的反应rootID.

想法2:将组件标记为简单/笨

通过将组件定义为"简单",react应该能够在呈现时跳过所有生命周期方法.反应已经这样做了芯反应,DOM组件(<p/>,<h1/>,等).很高兴扩展自定义组件以使用相同的优化.

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

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

结束和其他尝试

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

我们正在研究的一些项目包括:

有人遇到过类似的问题吗?你有什么能做的?谢谢.

performance render-to-string reactjs isomorphic-javascript react-dom

58
推荐指数
3
解决办法
2万
查看次数

React + Flux和服务器端渲染?(同构反应+通量)

使用同构应用程序设置应用程序的初始状态的一般做法是什么?没有Flux我会简单地使用类似的东西:

var props = { }; // initial state
var html = React.renderToString(MyComponent(props);
Run Code Online (Sandbox Code Playgroud)

然后通过快速把手渲染该标记并显示通过{{{reactMarkup}}.

在客户端设置初始状态我会做这样的事情:

if (typeof window !== 'undefined') {
    var props = JSON.parse(document.getElementById('props').innerHTML);
    React.render(MyComponent(props), document.getElementById('reactMarkup'));
}
Run Code Online (Sandbox Code Playgroud)

所以基本上你是在服务器和客户端上设置状态两次,但是React会比较这些差异,在大多数情况下,它不会通过重新渲染来影响性能.


当您在Flux架构中拥有操作和存储时,此原则将如何工作?在我的组件里面我可以做到:

getInitialState: function() {
  return AppStore.getAppState();
}
Run Code Online (Sandbox Code Playgroud)

但是现在我如何从服务器设置AppStore中的初始状态?如果我使用React.renderToString没有传递的属性,它将调用AppStore.getAppState()哪个不会有任何内容,因为我仍然不明白我将如何在服务器上的商店中设置状态?

2015年2月5日更新

我仍在寻找一种干净的解决方案,不涉及使用Fluxible,Fluxxor,Reflux等第三方Flux实施.

2016年8月19日更新

使用Redux.

javascript flux express reactjs isomorphic-javascript

42
推荐指数
2
解决办法
8677
查看次数

警告:React尝试在容器中重用标记,但校验和无效

我正在尝试使用isomorphic Node.js,Express,Webpack,React app工作.我收到以下错误.有关如何解决它的任何建议?

Warning: React attempted to reuse markup in a container but the checksum was invalid. This generally means that you are using server rendering and the markup generated on the server was not what the client was expecting. React injected new markup to compensate which works but you have lost many of the benefits of server rendering. Instead, figure out why the markup being generated is different on the client or server:
 (client) rgin:0;display:flex;-webkit-align-items:
 (server) rgin:0;display:flex;align-items:center;j

warning @ …
Run Code Online (Sandbox Code Playgroud)

node.js express reactjs webpack isomorphic-javascript

34
推荐指数
5
解决办法
3万
查看次数

Facebook React.js:你如何在服务器上呈现statefull组件?

我认为我在概念上缺少使用React.js进行服务器端渲染的东西

假设我想创建一个页面来显示来自服务器端数据库的项目,并使用输入字段来过滤它们.

我想要一个页面:

  • 响应像这样的URL /items?name=foobar
  • 使用React输入字段按名称过滤项目
  • 使用React组件显示已过滤项目的列表

假设我有一个公共REST API来查询客户端的项目.

从概念上讲,我在第一次请求(GET /items?name=foobar)时想要做的是:

  • 我希望我的输入字段显示用户作为参数传递的内容,因此我需要将查询参数('foobar')传递给react组件,作为'prop'(如initialName)

所以我尝试了这个:

 // A stateful component, maintaining the value of a query field
 var ItemForm = React.createClass({
    getInitialState : function () {
        return {
            name : this.props.initialName
        };
    },
    handleInputValueChanged : function() {
        var enteredName = this.refs.query.getDOMNode().value.trim();
        this.props.onNameChanged(enteredName);
    },
    render : function () {

        return React.DOM.form({
            children : [
                React.DOM.label({
                    children : "System name"
                }),
                React.DOM.input({
                    ref : "query",
                    value : this.state.name,
                    onChange : this.handleInputValueChanged …
Run Code Online (Sandbox Code Playgroud)

reactjs isomorphic-javascript

29
推荐指数
1
解决办法
1万
查看次数

从反应中做出宁静的api调用

我正在为同构javascript应用程序进行POC以从服务器端呈现html.POC正在使用简单的html,但我想进行api调用并获取json响应并发送到render函数.我试过各种各样的方法,但它没有用.你们其中一个请告诉我我失踪的地方.

我很反应js,任何帮助都会非常感激

loadCategoriesFromServer: function() {
        var self = this;

// get walking directions from central park to the empire state building
    var http = require("http");
    url = "api url here";
        var request = http.get(url, function (response) {
            // data is streamed in chunks from the server
            // so we have to handle the "data" event    
            var buffer = "", 
                data,
                route;

            response.on("data", function (chunk) {
                buffer += chunk;
            }); 

            response.on("end", function (err) {

              data = JSON.parse(buffer);

              //console.log(data.d);
              //console.log(data.d.Items);
                self.setState({
                    categories: …
Run Code Online (Sandbox Code Playgroud)

javascript reactjs isomorphic-javascript

22
推荐指数
2
解决办法
3万
查看次数

从React(Isomorphic应用程序)进行API调用时出现"Access-Control-Allow-Origin"问题

我使用React和Express遇到了同构JavaScript应用程序的问题.

我正在尝试使用axios.get在我的组件安装时发出HTTP请求

componentDidMount() {
  const url = 'http://ufc-data-api.ufc.com/api/v3/iphone/fighters/title_holders';
  axios.get(url).then( res => {
    //use res to update current state
  })
}
Run Code Online (Sandbox Code Playgroud)

我从API获得状态200 res,但我没有得到任何响应数据并在我的控制台中收到错误

XMLHttpRequest cannot load http://ufc-data-api.ufc.com/api/v3/iphone/fighters/title_holders. 
No 'Access-Control-Allow-Origin' header is present on the requested resource. 
Origin 'http://localhost:3000' is therefore not allowed access.
Run Code Online (Sandbox Code Playgroud)

但是,如果我在server.js中发出请求

const url = 'http://ufc-data-api.ufc.com/api/v3/iphone/fighters/title_holders';
axios.get(url).then(res => {
    //console.log(res);
});
Run Code Online (Sandbox Code Playgroud)

它工作正常,我在服务器启动时获得响应数据.这是实际API的问题还是我做错了什么?如果这是一个CORS问题,我猜测server.js中的请求也不起作用?谢谢!

javascript node.js reactjs isomorphic-javascript axios

19
推荐指数
6
解决办法
6万
查看次数

同构/通用反应中的图像onLoad事件 - 加载图像后注册事件

在同构呈现的页面图像可以在主script.js文件之前下载.因此,可以在react注册onLoad事件之前加载图像- 从不触发此事件.

script.js

constructor(props) {
    super(props);
    this.handleImageLoaded = this.handleImageLoaded.bind(this);
}

handleImageLoaded() {
    console.log('image loaded');
} 

render() {
    return (
        <img src='image.jpg' onLoad={this.handleImageLoaded} />
    );
}
Run Code Online (Sandbox Code Playgroud)

场景1 - image.jpg大于script.js

image.jpg比script.js大

在这种情况下一切正常.在最终加载图像之前注册事件,因此在控制台中是image loaded消息.


场景2 - image.jpg小于script.js

image.jpg小于script.js

在这种情况下,您可以看到帖子开头描述的问题.onLoad事件未触发.


为了onLoad方案2中触发事件,我该怎么办?


编辑:Soviut答案实施

要检测渲染时图像是否准备好,您应该检查complete纯javascript img对象上的属性:

constructor(props) {
    super(props);
    this.state = { loaded: false };
    this.handleImageLoaded = this.handleImageLoaded.bind(this);
    this.image = React.createRef();
}

componentDidMount() {
    const img …
Run Code Online (Sandbox Code Playgroud)

javascript reactjs isomorphic-javascript

18
推荐指数
4
解决办法
1万
查看次数

使用React动态加载样式表

我正在建立一个CMS系统来管理营销登陆页面.在"编辑登录页面"视图中,我希望能够为用户正在编辑的任何登录页面加载相关的样式表.我怎么能用React做这样的事情?

我的应用程序是完全React,同构,在Koa上运行.我的相关页面的基本组件层次结构看起来像这样:

App.jsx (has `<head>` tag)
??? Layout.jsx (dictates page structure, sidebars, etc.)
    ??? EditLandingPage.jsx (shows the landing page in edit mode)
Run Code Online (Sandbox Code Playgroud)

着陆页的数据(包括要加载的样式表的路径)是异步提取EditLandingPageComponentDidMount.

如果您需要任何其他信息,请与我们联系.很想得到这个想法!

额外奖励:我还想在离开页面时卸载样式表,我认为我可以反过来回答任何问题ComponentWillUnmount,对吧?

javascript stylesheet reactjs isomorphic-javascript

15
推荐指数
3
解决办法
3万
查看次数

在Isomorphic Redux应用程序中设置cookie的位置?

我有关于redux和同构应用的3个一般问题:

  • 在客户端和服务器之间共享"运行时"数据的最佳方法是什么? 例如,当用户登录远程API时,我将会话对象存储在cookie中.这样,下次客户端请求我的前端时,前端服务器可以读取cookie并使用之前的会话初始化redux存储.这样做的缺点是客户端HAS在启动时验证/无效会话(例如,在根组件的componentDidMount中).我应该请求会话服务器端而不是从cookie中读取它吗?
  • 我应该在哪里执行cookie存储操作,在动作创建者或者reducers中?我应该将cookie存储在处理用户会话的reducer中吗?
  • 我应该在哪里执行重定向用户的操作(通过react-router)?我的意思是当我的用户成功登录时,我应该从哪里调度重定向操作(一旦登录承诺解决后从loginActionCreator解决?),在其他地方?)

提前致谢.

javascript node.js reactjs isomorphic-javascript redux

15
推荐指数
2
解决办法
5833
查看次数

Webpack条件要求

我正在用webpack编写一个同构的Key Value Store.

这是我目前加载库的方法,这显然不起作用,因为webpack想解决这两个问题require.什么是正确的方法?

var db = null;

if (typeof window === 'undefined') {
    // node context
    db = require('level');
} else {
    // browser context
    db = require('gazel');
}
Run Code Online (Sandbox Code Playgroud)

我知道,你可以为webpack 提供一个目标.但我不知道如何使用它.

谢谢!

javascript leveldb webpack isomorphic-javascript

13
推荐指数
2
解决办法
1万
查看次数