(译文)React----React应用程序流式服务端渲染
好处
React16推出了流式服务端渲染,它允许你并行地分发HTML片段。这样可以让渲染
出的首字节有意义的内容给用户速度更快。
(例子1,上面部分是一次性转换,下面是流渲染,两种方式)
而且相对renderToString,流是异步的。这个可以让你的Node.js服务一次性渲染多个请求,并且保持在高请求压力环境下的及时响应。在一个持续的时间内,如果网络阻塞了,它可以停止React的渲染,并且不会因为重的网络请求影响其他轻请求。
实现: 用renderToNodeStream
import { renderToNodeStream } from 'react-dom/server';
import Frontend from '../client';
app.use('*', (request, response) => {
// 一开始发送有意义的页面部分
response.write('<html><head><title>Page</title></head><body><div id="root">');
// 把组件渲染成流,并且给Response
const stream = renderToNodeStream(<Frontend />);
stream.pipe(response, { end: 'false' });
// 当React渲染结束后,发送剩余的HTML部分给浏览器
stream.on('end', () => {
response.end('</div></body></html>');
});
});
(以上是例子2)
流是怎么工作的
renderToNodeStream返回了一个可读流,可以比作水龙头:它有源源不断的水,只是被堵住了,等待别人把它拧开。如果用这个可读流(如果把水龙头打开),只需要监听“data”时间就可以了(如果有新数据到了会自动触发)
代码类似这样:
import { renderToNodeStream } from 'react-dom/server';
const stream = renderToNodeStream(<Frontend />);
stream.on('data', (data) => {
console.log(JSON.stringify(data));
});
但是我们看例子2并没有监听”data“事件,而是直接把流pipe给了response对象。其实啊,
response对象在Node.js中是一个可写流,可以比做下水道。可读流通过pipe给可写流时,
可读流的数据会被分块发给可写流(就像是水龙头直接和下水道连接了一样,水源源不断流通)。
可写流可以对数据(水)进行任意的处理。
在我们的例子中,我们把组件渲染出来的流(html片段)给了response,response会把片段发给请求的客户端(比如浏览器)。
(可以看到First Byte明显前移动了,说明流渲染更快;因为并行的原因,片段渲染也更快了)
在Node.js中缓存HTML
const originalSend = response.send;
response.send = (html, ...other) => {
// 保证不缓存错误状态
if (response.statusCode > 100 && response.statusCode < 300) cache.put(request.path, html)
originalSend(html, ...other);
}
采用Express的中间件,提供缓存文件服务:
app.use('*', (request, response, next) => {
if (cache.has(request.path)) {
//如果缓存中有这个路径,则返回HTML
cache.get(request.path).then(html => response.send(html));
} else {
//否则就直接渲染
next();
}
})
接下来的问题是:如何渲染HTML,当你直接把htm的可写流pipe给了response流。因为response.send不会再被调用了,你也无法访问整个HTML文档。
缓存流HTML:transform streams
transform streams是什么?它就像是一个水龙头的过滤器。可读流经过它转换后才会给可写流。
在我们这里,我们只是想要缓存HTML并不会转化数据,具体怎么做,看代码:
import { Transform } from 'stream';
const createCacheStream = (key) => {
const bufferedChunks = [];
return new Transform({
//每一个HTML片段都会调用 transform()
transform(data, enc, cb) {
// 把HTML片段(Buffer)保存在内存中
bufferedChunks.push(data);
// 数据原封不动地给到下一个可读流
cb(null, data);
},
// 当所有的事件都做完后会调用flush()
flush(cb) {
// 通过连接HTML片段得到完整的html
// 并缓存起来
cache.set(key, Buffer.concat(bufferedChunks))
cb();
}
});
}
然后我们可以在我们的服务端渲染代码中使用它:
app.use('*', (request, response) => {
// 通过过滤器(transform streams)创建了缓存
let cacheStream = createCacheStream(request.path);
// cachesStream接上Response
cacheStream.pipe(response);
//先把首部分写到cacheStream
cacheStream.write('<html><head><title>Page</title></head><body><div id="root">');
// 创建了渲染流
const renderStream = renderToNodeStream(<Frontend />);
// 渲染流接上cacheStream
renderStream.pipe(cacheStream, { end: false });
renderStream.on('end', () => {
// 一旦结束渲染则做剩余部分的输出
cacheStream.end('</div></body></html>');
});
})
以上就是主要内容
原文链接:
https://zeit.co/blog/streaming-server-rendering-at-spectrum?nsukey=uW6M5M2uTd6F3Nc1u6tAVuAMGhbsBnpEuVplgUQLBlKevYZGGYN%2Bi1m6RocmDu%2F9367Zl71zSNn%2BkcWnaXcdX7bmeFLEyjbMMVsl5VtaBTfAvX8iNXgXMdbYWxVuuAealdKz8wkNfwEQtp4yLxknnredPgKISZUp%2BuR420YfPbpg8dW1lJMnpBMwNAJYMFZ0
作者知乎/公众号:前端疯 (一群热爱前端的一线程序员维护,想要用前端改变世界。)

(译文)React----React应用程序流式服务端渲染的更多相关文章
- 教你如何在React及Redux项目中进行服务端渲染
服务端渲染(SSR: Server Side Rendering)在React项目中有着广泛的应用场景 基于React虚拟DOM的特性,在浏览器端和服务端我们可以实现同构(可以使用同一份代码来实现多端 ...
- react+redux教程(六)redux服务端渲染流程
今天,我们要讲解的是react+redux服务端渲染.个人认为,react击败angular的真正“杀手锏”就是服务端渲染.我们为什么要实现服务端渲染,主要是为了SEO. 例子 例子仍然是官方的计数器 ...
- React 在服务端渲染的实现
原文地址:Server-Side React Rendering 原文作者:Roger Jin 译者:牧云云 React 在服务端渲染的实现 React是最受欢迎的客户端 JavaScript 框架, ...
- [译]React 在服务端渲染的实现
原文地址:Server-Side React Rendering 原文作者:Roger Jin React 在服务端渲染的实现 React是最受欢迎的客户端 JavaScript 框架,但你知道吗(可 ...
- React 服务端渲染最佳解决方案
最近在开发一个服务端渲染工具,通过一篇小文大致介绍下服务端渲染,和服务端渲染的方式方法.在此文后面有两中服务端渲染方式的构思,根据你对服务端渲染的利弊权衡,你会选择哪一种服务端渲染方式呢? 什么是服务 ...
- React 16 服务端渲染的新特性
React 16 服务端渲染的新特性 React 16 中关于服务端渲染的新特性 快速介绍React 16 服务端渲染的新特性,包括数组.性能.流等 React 16 终于来了!
- react基础学习和react服务端渲染框架next.js踩坑
说明 React作为Facebook 内部开发 Instagram 的项目中,是一个用来构建用户界面的优秀 JS 库,于 2013 年 5 月开源.作为前端的三大框架之一,React的应用可以说是非常 ...
- react+laravel与服务端渲染的几点思考
一.前后端完全分离 1.用React.js做MVC中的V,剩下的交给Laravel 2.Laravel用来做API接口开发. 3.好处:实现了前后端开发的分离,从而加快前后端开发效率.另外若是多端的如 ...
- React 服务端渲染方案完美的解决方案
最近在开发一个服务端渲染工具,通过一篇小文大致介绍下服务端渲染,和服务端渲染的方式方法.在此文后面有两中服务端渲染方式的构思,根据你对服务端渲染的利弊权衡,你会选择哪一种服务端渲染方式呢? 什么是服务 ...
随机推荐
- TypeError: Error #1034: 强制转换类型失败:无法将 "" 转换为 Array。
1.错误描述 TypeError: Error #1034: 强制转换类型失败:无法将 "" 转换为 Array. at mx.charts.series::LineSeries/ ...
- 小实验3:实现haproxy的增、删、查
# Author:Alano # -*- conding:utf-8 -*- # 这里有一个问题:为什么手动删除了haproxy_new中的内容,但是执行添加命令的时候依然显示数据已经存在? f = ...
- 页面jquery调试的一个宝贵经验(类似于Eclipse中的写出一个对象点它的方法时候用alt加/可以跳出来它所有的方法)
案例讲解 一,html片段 <div class="page-upload"> <div class="tab-wrapper2"> & ...
- C#图解教程 第十章 结构
结构 什么是结构结构是值类型对结构赋值构造函数和析构函数 实例构造函数静态构造函数构造函数和析构函数小结 字段初始化语句是不允许的结构是密封的装箱和拆箱结构作为返回值和参数 关于结构的其他信息 结构 ...
- TensorLayer官方中文文档1.7.4:API – 数据预处理
所属分类:TensorLayer API - 数据预处理¶ 我们提供大量的数据增强及处理方法,使用 Numpy, Scipy, Threading 和 Queue. 不过,我们建议你直接使用 Tens ...
- 【HNOI2004】宠物收养所(splay)
题面 Description 最近,阿Q开了一间宠物收养所.收养所提供两种服务:收养被主人遗弃的宠物和让新的主人领养这些宠物.每个领养者都希望领养到自己满意的宠物,阿Q根据领养者的要求通过他自己发明的 ...
- Bzoj2442:修剪草坪
Sol 一个很显然的暴力,设\(f[i]\)表示选到\(i\)的最优效率 每次枚举一段不与前面连续的长度小于\(k\)的区间转移来 # include <bits/stdc++.h> # ...
- iBrand 教程 0.1:Windows + Homestead 5 搭建 Laravel 开发环境
统一开发环境 为了保证在学习和工作过程中避免因为开发环境不一致而导致各种各样的问题,Laravel 官方为了我们提供了一个完美的开发环境 Laravel Homestead,让我们无需再本地安装 PH ...
- 八年架构师大咖首次揭秘,年薪50W秘籍!
序言 我是土生土长的老北京人,你们肯定觉得我很有钱,为啥呢? 因为觉得我是北京户口,其实你们错了,我的房子是靠我自己买的,父母基本上没帮到我什么,当然,我也不需要吧! 我只想说,作为一名程序员,我很自 ...
- sspanelv3魔改版邮件设置指南及常用配置
要进行SSpanel v3魔改版邮件设置,需要在设置文件(位于config/.config.php下)中修改两处内容: 1.设置发送邮件的方式 $System_Config['enable_email ...