node网页分段渲染详解


Posted in Javascript onSeptember 05, 2016

页面渲染,通常来说分为前端渲染以及后端渲染。前端渲染指的是服务端返回html框架以及模版,前端通过ajax异步请求拉取数据渲染模版,并动态修改dom,形成最终页面。服务端渲染则是服务端通过在后端拉取数据以及后端模版渲完整页面,并返回到客户端。2种方法各有好处,后端渲染带来的则是首屏时间的提高,减少请求次数,利于SEO等好处。但是传统后端直出渲染需要等到整个网页渲染完成,才能返回到客户端。假如某个区块拉取数据比较慢,影响了渲染的速度,那对于用户来说,等待的时候也会跟着变长对于后端渲染能否跟前端ajax渲染一样,分块分区域传统的服务端直出渲染,下面将提供一种解决方案-网页分段渲染。

首先我们先看下传统的渲染方式:

const http = require("http");
const fs = require("fs");
var tpl1 = '<!DOCTYPE html><html><head><title>测试render</title></head><body>helloword<p>$data1</p>';
var tpl2 = '<p>$data2</p></body></html>';
var html = '';

var server = http.createServer((req, res)=>{
 if(req.url!=="/favicon.ico"){
   res.writeHead(200, {
     'Content-Type' : 'text/html'
   });
   getDataOne((data1) => {
     getDataTwo((data2) => {
       res.end(tpl1.replace(/\$data1/g, data1) + tpl2.replace(/\$data2/g, data2));
     })
   });
 }
 }).listen(3000, '127.0.0.1');


function getDataOne(fn){
  setTimeout(() => {
     fn('11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111');
  }, 5000);
 }

 function getDataTwo(fn){
   setTimeout(() => {
     fn('22222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222');
   }, 5000);
 }

上面我们提供了一个简单的例子,通过访问http://127.0.0.1:3000 返回一个页面。其中渲染页面时,有2个耗时5秒的操作,可以假设为IO或者数据拉取。这个时候我们观察返回页面的时间是10秒,也就是说用户看到页面需要10秒钟。

node网页分段渲染详解

下面我们通过改造后端渲染方式,改为分段渲染。

const http = require("http");
const fs = require("fs");

var server = http.createServer((req, res)=>{
  if(req.url!=="/favicon.ico"){
    res.writeHead(200, {
      'Content-Type' : 'text/html',
      'Transfer-Encoding' : 'chunked'
    });

    getDataOne((data1) => {
      res.write('<!DOCTYPE html><html><head><title>测试render</title></head><body>helloword<p>$data1</p>'.replace(/\$data1/g, data1));
      getDataTwo((data2) => {
        res.end('<p>$data2</p></body></html>'.replace(/\$data2/g, data2));
      })
    });
 }
}).listen(3000, '127.0.0.1');

function getDataOne(fn1){
  setTimeout(() => {
   fn1('1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111');
 }, 5000);
 }

function getDataTwo(fn2){
  setTimeout(() => {
    fn2('22222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222');
  }, 5000);
}

通过设置http首部: Transfer-Encoding: chunked 即开启了分段传输的魔法。该编码方式存在http1.1中,一般在服务器生成HTTP回应是无法确定信息大小的,这时用Content-Length就无法事先写入长度,而需要实时生成消息长度,则服务器一般采用Chunked编码。

在进行Chunked编码传输时,在回复消息的头部有transfer-coding并定义为Chunked,表示将用Chunked编码传输内容。 下面我们看下修改后的效果:

node网页分段渲染详解

虽然总体的页面传输时间并没有变化,但是通过该方式,我们将响应时间缩短了一半,减少了用户等待的时间。在具体业务中,我们可以讲用户需要先看到的部分进行提前输出,将后端处理耗时较久的部分延迟输出,这就是分段传输渲染的优势。 注意如果服务器是nginx,有可能由于缓冲区的设置导致分段渲染无效,需要调整缓冲区大小。

Javascript 相关文章推荐
javascript实例--教你实现扑克牌洗牌功能
May 15 Javascript
JavaScript判断是否为数字的4种方法及效率比较
Apr 01 Javascript
Prototype框架详解
Nov 25 Javascript
Jquery插件之Fancybox丰富的弹出层效果附源码下载
Dec 02 Javascript
基于Bootstrap里面的Button dropdown打造自定义select
May 30 Javascript
浅谈JavaScript的闭包函数
Dec 08 Javascript
bootstrap弹出层的多种触发方式
May 10 Javascript
Node.js如何使用Diffie-Hellman密钥交换算法详解
Sep 05 Javascript
angular4 获取wifi列表中文显示乱码问题的解决
Oct 20 Javascript
微信小程序实现点击图片旋转180度并且弹出下拉列表
Nov 27 Javascript
jquery.tagsinput.js实现记录checkbox勾选的顺序
Sep 21 jQuery
javascript实现随机抽奖功能
Dec 30 Javascript
js对象浅拷贝和深拷贝详解
Sep 05 #Javascript
JS实现隐藏同级元素后只显示JS文件内容的方法
Sep 04 #Javascript
jQuery实现智能判断固定导航条或侧边栏的方法
Sep 04 #Javascript
angularjs实现文字上下无缝滚动特效代码
Sep 04 #Javascript
jQuery实现为LI列表前3行设置样式的方法【2种方法】
Sep 04 #Javascript
JS实现屏蔽网页右键复制及ctrl+c复制的方法【2种方法】
Sep 04 #Javascript
jQuery实现的自动加载页面功能示例
Sep 04 #Javascript
You might like
DEDE采集大师官方留后门的删除办法
2011/01/08 PHP
Zend的AutoLoad机制介绍
2012/09/27 PHP
PHP中替换键名的简易方法示例详解
2014/01/07 PHP
Codeigniter里的无刷新上传的实现代码
2019/04/14 PHP
tp5框架基于Ajax实现列表无刷新排序功能示例
2020/02/10 PHP
javascript URL锚点取值方法
2009/02/25 Javascript
防止动态加载JavaScript引起的内存泄漏问题
2009/10/08 Javascript
基于jquery的无限级联下拉框js插件
2011/10/29 Javascript
js批量设置样式的三种方法不推荐使用with
2013/02/25 Javascript
关于query Javascript CSS Selector engine
2013/04/12 Javascript
Javascript遍历table中的元素示例代码
2014/07/08 Javascript
jQuery获取标签文本内容和html内容的方法
2015/03/27 Javascript
ionic开发中点击input时键盘自动弹出
2016/12/23 Javascript
基于Bootstrap 3 JQuery及RegExp的表单验证功能
2017/02/16 Javascript
浅谈react.js 之 批量添加与删除功能
2017/04/17 Javascript
微信小程序实现循环动画效果
2018/07/16 Javascript
微信小程序实现商城倒计时
2020/11/01 Javascript
vue实现公告栏文字上下滚动效果的示例代码
2020/06/16 Javascript
jQuery实现移动端下拉展现新的内容回弹动画
2020/06/24 jQuery
JS制作简易计算器的实例代码
2020/07/04 Javascript
原生JS实现拖拽效果
2020/12/04 Javascript
Python自动连接ssh的方法
2015/03/07 Python
Python中shape计算矩阵的方法示例
2017/04/21 Python
TensorBoard 计算图的可视化实现
2020/02/15 Python
python画图常规设置方式
2020/03/05 Python
基于Python+QT的gui程序开发实现
2020/07/03 Python
UGG雪地靴荷兰官网:UGG荷兰
2016/09/09 全球购物
德国富尔达运动鞋店:43einhalb
2020/12/25 全球购物
DataReader和DataSet的异同
2014/12/31 面试题
学习之星事迹材料
2014/05/17 职场文书
机械设计及其自动化专业求职信
2014/06/09 职场文书
小学语文教研活动总结
2014/07/01 职场文书
小学少先队辅导员述职报告
2015/01/10 职场文书
社会实践单位意见
2015/06/05 职场文书
golang操作redis的客户端包有多个比如redigo、go-redis
2022/04/14 Golang
阿里面试Nacos配置中心交互模型是push还是pull原理解析
2022/07/23 Java/Android