通常,当客户端请求一个包含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. 云计算和大数据时代网络技术揭秘(十二)自定义网络SDN

    软件定义网络——SDN SDN是网络技术热点,即软件定义网络,OpenFlow是实现SDN思想的一个框架标准, open是指公开.开放,具体为控制平面的规则由各个通信厂家自定义变为公开的技术标准, f ...

  2. IOS 导航栏

    系统状态栏改为白色:在Supporting Files文件的info.plist文件中添加 新的key,名字为View controller-based status bar appearance,并 ...

  3. oracle安装心得

    1.官网下载 oracle 11g r2 2.官网下载的oracle包括两个文件夹file1和file2,需要将解压后的file2中的stage-components文件夹下的内容复制到file1-s ...

  4. LeetCode OJ-- Wildcard Matching **@

    https://oj.leetcode.com/problems/wildcard-matching/ 模拟通配符的匹配 做法非常好 class Solution { public: bool isM ...

  5. python基础语法(3)

    七.面向对象编程 python支持面向对象编程:类和对象是面向对象编程的两个主要方面,类创建一个新的类型,对象是这个类的实例. 对象可以使用普通的属于对象的变量存储数据,属于对象或类的变量被称为域:对 ...

  6. hexo框架-next主题-github搭建个人博客

    IT`huhui 的前言录 我在GITHUB的个人站点:http://ithuhui.cn 这里遇到的很多问题都是亲身解决后写的.还有遇到不懂可以邮件M我 在这里要感谢浮生志的博客教程,很多我一开始不 ...

  7. crontab计划任务

    编辑crontab文件:crontab -e 查看crontab日志: tail -100f /var/log/cron 编辑格式: 基本格式 : * * * * * command 分 时 日 月 ...

  8. ASP.NET MVC学习之模型绑定(2)

    3.手工调用模型绑定 很多情况下我们都是通过形参的方式接收来自http流中的数据,这看似是完美的,但是缺少了很多过程中的控制,所以我们就需要使用手工的方式进行绑定.下面我们通过一个例子来说明,首先打开 ...

  9. Dynamic CRM 2013学习笔记(二十六)报表设计:Reporting Service报表 动态参数、参数多选全选、动态列、动态显示行字体颜色

    上次介绍过CRM里开始报表的一些注意事项:Dynamic CRM 2013学习笔记(十五)报表入门.开发工具及注意事项,本文继续介绍报表里的一些动态效果:动态显示参数,参数是从数据库里查询出来的:参数 ...

  10. Nim教程【二】

    第一篇教程1秒内就被管理员从首页踢掉了 管理员嫌内容太少,没有含金量,这次多写一些. 这应该是国内第一个关于Nim入门的系列教程 好,闲话休提,言归正传 Nim介绍 Nim代码会编译成C语言的代码,再 ...