(译文)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 服务端渲染方案完美的解决方案
最近在开发一个服务端渲染工具,通过一篇小文大致介绍下服务端渲染,和服务端渲染的方式方法.在此文后面有两中服务端渲染方式的构思,根据你对服务端渲染的利弊权衡,你会选择哪一种服务端渲染方式呢? 什么是服务 ...
随机推荐
- 芝麻HTTP:Scrapy小技巧-MySQL存储
这两天上班接手,别人留下来的爬虫发现一个很好玩的 SQL脚本拼接. 只要你的Scrapy Field字段名字和 数据库字段的名字 一样.那么恭喜你你就可以拷贝这段SQL拼接脚本.进行MySQL入库处理 ...
- freemark标签中输出boolean值
private boolean showHeader=true; public boolean getShowHeader(){ return this.showHeader; } public bo ...
- 你需要了解的高可用方案之使用keepalived搭建双机热备一览
在之前一篇使用nginx搭建高可用的解决方案的时候,很多同学会问,如果nginx挂掉怎么办,比如下面这张图: 你可以清楚的看到,如果192.168.2.100这台机器挂掉了,那么整个集群就下线了,这个 ...
- 【BZOJ1996】合唱队(动态规划)
[BZOJ1996]合唱队(动态规划) 题面 BZOJ 题解 很容易的一道题 因为每个人不是放在了左边就是放在了右边 所以每次放好的人必定是原序列的一个子串 所以,很容易想到区间\(dp\) 设\(f ...
- Luogu3444:[POI2006]ORK-Ploughing
题意 见luogu Sol 贪心+枚举 如果知道最后一次是消除一行 那么一定消了\(n\)行 此时只要消的列最小就好了 枚举每列从上往下消到哪里,那么下面消的越小越好 那么就有了贪心策略: 先消左右的 ...
- WC2006水管局长(加强)
倒过来就变成了加边 然后就直接LCT # include <stdio.h> # include <stdlib.h> # include <iostream> # ...
- 【noip模拟】修长城
Time Limit: 1000ms Memory Limit: 256MB Description 大家都知道,长城在自然条件下会被侵蚀,因此,我们需要修复.现在是21世纪,修复长城的事情当然 ...
- MyBatis的三层级联和二层缓存
我们这里说的三层级联和二级缓存其实也是MyBatis映射器的知识点,只是因为比较难理解,所以单独拿出来讲解,下面是三层级联的内容: 我们知道,在数据库中包含着一对一,一对多 ...
- 《深入理解Bootstrap》读书笔记(二)
列表 1.普通列表 普通列表的使用没有什么变化,只是在原本的基础上对margin和行间距做了一些调整. 2.有序列表 有序列表的使用也是没有什么变化,只是在原本的基础上对margin和行间距做了一些调 ...
- 谁能用通俗的语言解释一下什么是 RPC 框架?
转载自知乎:https://www.zhihu.com/question/25536695 知乎上很多问题的答案还是很好的,R大就经常在上面回答问题 关于RPC你的题目是RPC框架,首先了解什么叫RP ...