通常,当客户端请求一个包含React组件页面的时候,服务端首先响应输出这个页面,客户端和服务端有了第一次交互。然后,如果加载组件的过程需要向服务端发出Ajax请求等,客户端和服务端又进行了一次交互,这样,耗时相对较长。服务端是否可以在页面初次加载时把所有方面渲染好再一次性响应给客户端呢?

「React同构直出」就是用来解决这个问题的,做到「秒开」页面。过程大致是这样滴:

1、在需要同构直出的页面(比如是index.html)放上占位符

<div id="root">@@@</div>
###

以上,当客户端发出首次请求,服务端渲染出组件的html内容放@@@这个位置,然后服务端再渲染出类似<script>renderApp()</script>这样的js代码段把组件最终渲染到DOM上。也就是说,renderApp方法实际上就是在渲染组件。

2、而为了直接调用renderApp方法,必须让renderApp方法成为window下的方法

window.renderApp = function(){ReactDOM.render(...)}

3、服务端取出index.html,渲染出占位符的内容,替代占位符,并一次性响应给客户端

通过一个例子来体会。

文件结构

browser.js(在这里把渲染组件的过程赋值给window.renderApp)
bundle.js(把browser.js内容bundle到这里)
Component.js(组件在这里定义)
express.js(服务端)
index.html(同构直出的页面)
package.json

index.html,直出页面放上占位符

<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>Untitled Document</title>
</head>
<body> <div id="root">@@@</div>
<script src="bundle.js"></script>
###
</body>
</html>

Component.js,在这里定义组件

var React = require('react');
var ReactDOM = require('react-dom'); var Component = React.createClass({
clickHandler: function(){
alert(this.props.msg)
}, render: function(){
return React.createElement('button', {onClick: this.clickHandler}, this.props.msg)
} }) module.exports = Component;

browser.js,把组件渲染过程赋值给window对象

var React = require('react');
var ReactDOM = require('react-dom'); var Component = React.createFactory(require('./Component')); window.renderApp = function(msg){
ReactDOM.render(Component({msg: msg}), document.getElementById('root'));
}

可以通过<script>render()</script>来触发组件的渲染。稍后,在服务端会把这段代码渲染出来。

express.js,服务端

以上,需要直出的页面有了占位符,定义了组件,并把渲染组件的过程赋值给了window对象,服务端现在要做的工作就是:生成组件的html和渲染组件的js,放到直出页面index.html的占位符位置。

var express  = require('express');
var React = require('react');
var ReactDOMServer = require('react-dom/server');
var fs = require('fs');
var Component = React.createFactory(require('./Component')); //原先把文件读出来
var BUNDLE = fs.readFileSync('./bundle.js',{encoding:'utf8'});
var TEMPLATE = fs.readFileSync('./index.html',{encoding:'utf8'}); var app = express(); function home(req, res){
var msg = req.params.msg || 'Hello';
var comp = Component({msg: msg}); //@@@占位符的地方放组件
var page = TEMPLATE.replace('@@@', ReactDOMServer.renderToString(comp)); //###占位符的地方放js
page = page.replace('###', '<script>renderApp("'+msg+'")</script>')
res.send(page);
} //路由
app.get('', home);
app.get('/bundle.js', function(req, res){
res.send(BUNDLE);
})
app.get('/:msg', home); app.listen(4000);

package.json中的配置

"scripts": {
"start": "watchify ./browser.js -o ./bundle.js"
},

运行:npm start

运行:node express.js

浏览:localhost:4000

项目地址:https://github.com/darrenji/ReactIsomorphicSimpleExample

React同构直出原理浅析的更多相关文章

  1. 腾讯新闻构建高性能的 react 同构直出方案

    在腾讯新闻抢金达人活动 node 同构直出渲染方案的总结文章中我们整体了解了下同构直出渲染方案在我们项目中的使用.正如我在上篇文章结尾所说的: 应用型技术的难点不是在克服技术问题,而是在于能够不断的结 ...

  2. React同构直出优化总结

    收录待用,修改转载已取得腾讯云授权 作者:郭林烁 joeyguo 原文地址 React 的实践从去年在 PC QQ家校群开始,由于 PC 上的网络及环境都相当好,所以在使用时可谓一帆风顺,偶尔遇到点小 ...

  3. 面向亿万级用户的QQ一般做什么?——兴趣部落的Web同构直出分享

    作者:李强,腾讯web开发工程师 商业转载请联系腾讯WeTest获得授权,非商业转载请注明出处. 原文链接:http://wetest.qq.com/lab/view/348.html 一.什么是同构 ...

  4. 面向亿万级用户的QQ一般做什么?——兴趣部落的 Web 同构直出分享

    欢迎大家前往腾讯云社区,获取更多腾讯海量技术实践干货哦~ 作者:李强,腾讯web开发工程师商业转载请联系腾讯WeTest获得授权,非商业转载请注明出处.原文链接:http://wetest.qq.co ...

  5. Vue(SPA) WebPack模块化打包、SEO优化(Vue SSR服务端同构直出)、全浏览器兼容完整解决方案

    白驹过隙,时光荏苒 大概去年这个时候写了angular 结合webpack的一套前端方案,今年此时祭出vue2结合webpack的一套前端方案. 明年的这个时候我又是在做什么... 读在最前面: 1. ...

  6. 腾讯新闻抢金达人活动node同构直出渲染方案的总结

    我们的业务在展开的过程中,前端渲染的模式主要经历了三个阶段:服务端渲染.前端渲染和目前的同构直出渲染方案. 服务端渲染的主要特点是前后端没有分离,前端写完页面样式和结构后,再将页面交给后端套数据,最后 ...

  7. React直出实现与原理

    前一篇文章我们介绍了虚拟DOM的实现与原理,这篇文章我们来讲讲React的直出. 比起MVVM,React比较容易实现直出,那么React的直出是如何实现,有什么值得我们学习的呢? 为什么MVVM不能 ...

  8. 打造高可靠与高性能的React同构解决方案

    前言 随着React的兴起, 结合Node直出的性能优势和React的组件化,React同构已然成为趋势之一.享受技术福利的同时,直面技术挑战,在复杂场景下,挑战10倍以上极致的性能优化. 什么是同构 ...

  9. React同构起步

    React同构从0到1 前言 如果你想快速做react同构的新项目建议你去了解next.js等成熟框架,本教程仅限于想了解如何从0开始实现一个同构环境过程的同学,对于想改造现有spa项目的同学也很有帮 ...

随机推荐

  1. HDU 2689Sort it 树状数组 逆序对

    Sort it Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Sub ...

  2. gawk快速入门

    基本定义: gawk 的主要功能是针对文本的每一行执行被指定的 actions. 命令格式: gawk option program file option: -F 指定的分隔符,默认的分隔符是空格, ...

  3. 学习Linux所需软件

    一:  VMware虚拟机 二:VMware_Install_Cleaner 虚拟机卸载 三:XShall

  4. (转).NET 4.5中使用Task.Run和Parallel.For()实现的C# Winform多线程任务及跨线程更新UI控件综合实例

    http://2sharings.com/2014/net-4-5-task-run-parallel-for-winform-cross-multiple-threads-update-ui-dem ...

  5. Linux 修改IP地址

    vi /etc/sysconfig/network-scripts/ifcfg-eth0 DEVICE="eth0" BOOTPROTO="static" #静 ...

  6. heartbeat安装与配置

    Hearbeat和keepalived区别 Keepalived使用的vrrp协议方式,虚拟路由冗余协议 (Virtual Router Redundancy Protocol,简称VRRP): He ...

  7. Python 1 —— Start Up

    作为一种脚本语言,Python号称是万能的胶带语言,可以非常好的作为多种语言之间的粘合剂,因此从多种语言融合的角度看,学习Python是非常有必要的!下面对学习Python当中的一些重点进行记录! 一 ...

  8. [数据结构] N皇后问题

    代码: #include <iostream> #include <string.h> #include <algorithm> using namespace s ...

  9. 待实验:Android 增量升级

    参考资料: 增量升级(省流量更新)的Android客户端实现  http://blog.csdn.net/sgwhp/article/details/9009427 http://my.oschina ...

  10. QT 应用部署到Android的终端步骤

    参考网址: http://blog.csdn.net/syrchina/article/details/17335945