React同构直出原理浅析
通常,当客户端请求一个包含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同构直出原理浅析的更多相关文章
- 腾讯新闻构建高性能的 react 同构直出方案
在腾讯新闻抢金达人活动 node 同构直出渲染方案的总结文章中我们整体了解了下同构直出渲染方案在我们项目中的使用.正如我在上篇文章结尾所说的: 应用型技术的难点不是在克服技术问题,而是在于能够不断的结 ...
- React同构直出优化总结
收录待用,修改转载已取得腾讯云授权 作者:郭林烁 joeyguo 原文地址 React 的实践从去年在 PC QQ家校群开始,由于 PC 上的网络及环境都相当好,所以在使用时可谓一帆风顺,偶尔遇到点小 ...
- 面向亿万级用户的QQ一般做什么?——兴趣部落的Web同构直出分享
作者:李强,腾讯web开发工程师 商业转载请联系腾讯WeTest获得授权,非商业转载请注明出处. 原文链接:http://wetest.qq.com/lab/view/348.html 一.什么是同构 ...
- 面向亿万级用户的QQ一般做什么?——兴趣部落的 Web 同构直出分享
欢迎大家前往腾讯云社区,获取更多腾讯海量技术实践干货哦~ 作者:李强,腾讯web开发工程师商业转载请联系腾讯WeTest获得授权,非商业转载请注明出处.原文链接:http://wetest.qq.co ...
- Vue(SPA) WebPack模块化打包、SEO优化(Vue SSR服务端同构直出)、全浏览器兼容完整解决方案
白驹过隙,时光荏苒 大概去年这个时候写了angular 结合webpack的一套前端方案,今年此时祭出vue2结合webpack的一套前端方案. 明年的这个时候我又是在做什么... 读在最前面: 1. ...
- 腾讯新闻抢金达人活动node同构直出渲染方案的总结
我们的业务在展开的过程中,前端渲染的模式主要经历了三个阶段:服务端渲染.前端渲染和目前的同构直出渲染方案. 服务端渲染的主要特点是前后端没有分离,前端写完页面样式和结构后,再将页面交给后端套数据,最后 ...
- React直出实现与原理
前一篇文章我们介绍了虚拟DOM的实现与原理,这篇文章我们来讲讲React的直出. 比起MVVM,React比较容易实现直出,那么React的直出是如何实现,有什么值得我们学习的呢? 为什么MVVM不能 ...
- 打造高可靠与高性能的React同构解决方案
前言 随着React的兴起, 结合Node直出的性能优势和React的组件化,React同构已然成为趋势之一.享受技术福利的同时,直面技术挑战,在复杂场景下,挑战10倍以上极致的性能优化. 什么是同构 ...
- React同构起步
React同构从0到1 前言 如果你想快速做react同构的新项目建议你去了解next.js等成熟框架,本教程仅限于想了解如何从0开始实现一个同构环境过程的同学,对于想改造现有spa项目的同学也很有帮 ...
随机推荐
- Apache-Commons包作用说明
Apache Commons包含了很多开源的工具,用于解决平时编程经常会遇到的问题,减少重复劳动.项目地址http://commons.apache.org/ Commons BeanUtils 提供 ...
- Linux如何学习
一:如何提问 1. 尝试自己解决 帮助文档 示例 2. 提问的要求 问题要详细(能被别人看懂, 一个知识点) 报错信息(截图) 二:1.Linux区分大小写 2.所有内容以文件形式保存,包括硬件(一切 ...
- Odoo10 变化
官方在 https://www.odoo.com/forum/help-1/question/fyi-what-has-odoo-r-d-been-working-on-lately-106945 发 ...
- python 中 深拷贝和浅拷贝的理解
在总结 python 对象和引用的时候,想到其实 对于python的深拷贝和浅拷贝也可以很好对其的进行理解. 在python中,对象的赋值的其实就是对象的引用.也就是说,当创建一个对象,然后赋给另外一 ...
- [php-src]一个Php扩展的结构
内容均以php5.6.14为例. 要拥有一个PHP扩展的架子,使用源码中准备好的 /ext/ext_skel 工具,可以生成一个可运行的扩展骨架. 不加选项运行 ./ext_skel,可查看所有可用选 ...
- oracle 未找到提供程序。该程序可能未正确安装
使用ADO连接oracle数据库时,连接串使用Provider=OraOLEDB.Oracle时提示"未找到提供程序.该程序可能未正确安装". 原因:由于我之间安装oracle_o ...
- Failed to execute goal on project MakeFriends: Could not resolve dependencie The POM for .chengpai.jtd:jtd-service-api:jar:1.0-SNAPSHOT is missing, no dependency information available
本笔者在学习maven的基础,然后建立了一个maven的项目,然后想对其进行依赖操作,pom.xml进行依赖操作时候出现了这样的错误,说是找不到这个依赖的包,但是事实上已经导入了这个包. 同时,也在m ...
- Java入门 任务表
Java IO Java ,MySQL Java Internet 线程,同步 冒泡法排序 1.
- 升级adt插件后,eclipse突然出现Unable to build: the file dx.jar was not loaded from the SDK folder 错误
旧版的SDK管理器里面最高只能安装Android 3.2 API,需要更新SDK管理器版本后才能安装Android 4.0.Android 4.1,方法如下: http://blog.csdn.net ...
- Kali Linux Web 渗透测试视频教程—第十四课-arp欺骗、嗅探、dns欺骗、session劫持
Kali Linux Web 渗透测试视频教程—第十四课-arp欺骗.嗅探.dns欺骗.session劫持 文/玄魂 目录 Kali Linux Web 渗透测试—第十四课-arp欺骗.嗅探.dns欺 ...