(译文)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 服务端渲染方案完美的解决方案
最近在开发一个服务端渲染工具,通过一篇小文大致介绍下服务端渲染,和服务端渲染的方式方法.在此文后面有两中服务端渲染方式的构思,根据你对服务端渲染的利弊权衡,你会选择哪一种服务端渲染方式呢? 什么是服务 ...
随机推荐
- /opt/apache-tomcat-7.0.57/conf/catalina.policy(权限不够)
1 错误描述 /opt/apache-tomcat-7.0.57/conf/catalina.policy(权限不够) 2 错误原因 3 解决办法
- org.hibernate.MappingException
1.错误描述 org.springframework.beans.factory.BeanCreationException:Error creating bean with name 'sessio ...
- but the supplied types were (flex.messaging.io.amf.ASObject) and converted to (null)."
1.错误描述 [RPC Fault faultString="Cannot invoke method 'saveOrUpdate'. " faultCode="Ser ...
- CF374 Maxim and Array
贪心 如果有0先变成非0 如果负数的个数 应该变为偶数 之后就是每次将绝对值最小的值加K #include<bits/stdc++.h> using namespace std; cons ...
- iOS - Mac 常用设置
1.Finder 中显示资源库 方法一: 在 "终端" 中输入下面的命令: 显示: $ chflags nohidden ~/Library/ 隐藏: $ chflags hidd ...
- 省市县从数据库读出来的list数据转换成json格式的数据
一,数据源 1.1,数据库查出来的数据是 两张表先各自左外连接,然后在相互左外连接查找省市县的数据(业务需求必须这样做,省市去的是第一张表,而市县取的是第二张表,两张表中间通过市的名字连接)见这个博文 ...
- WPF基础篇之命名空间
WPF中XAML与C#一样,也有自己独立的编译器.XAML会被解析和编译,最终形成微软的中间语言存储在程序集中.在解析和编译XAML的语言过程中,我们经常需要告诉编译器一些重要的信息,比如XAML代码 ...
- 改造 vue-cli 脚手架
改造 vue-cli 脚手架 注意,这里使用的 vue-cli 的版本为 2.8.2,不同版本的 vue-cli 可能会有些许不一样. 一.配置多页面 项目开发目录: 需要注意一点,每个页面的文件夹命 ...
- iOS 双击tabbar刷新页面
/*在继承UITabBarController控制器中*/ #pragma mark <UITabBarControllerDelegate> -(void)tabBarControlle ...
- 一个小的tab切换插件
1//使用 var t1=new Tab({ etype:'onmou',//默认点击触发,如果事件写错了,当作单击 autoplay:2000,//有时间值(按照事件自动播放)和false(不自动播 ...