node网页分段渲染与bigpipe(一)

页面渲染,通常来说分为前端渲染以及后端渲染。前端渲染指的是服务端返回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秒钟。

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

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编码传输内容。 下面我们看下修改后的效果:

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

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏破晓之歌

移动web开发适配秘籍Rem(推荐) 原

691
来自专栏贾鹏辉的技术专栏@CrazyCodeBoy

教你轻松修改React Native端口

告诉大家一个好消息,为大家精心准备的React Native视频教程发布了,大家现可以看视频学React Native了。 当我们运行一个React Na...

3124
来自专栏十月梦想

css3动画效果transition的用法

上述的例子的功能介绍:鼠标移入色块div,div的宽度则在3s内width变为500px;

664
来自专栏极客编程

简单介绍一下vue2.0

Vue是用于构建用户界面的渐进框架。作者尤雨熙特别强调它与其他的框架不同,Vue是渐进式的框架,可以逐步采用,不必一下就通过框架去重构项目。 另外Vue的核心库...

1272
来自专栏Python攻城狮

Django教程(二)- Django视图与网址进阶1. HTML表单2.CSRF3.代码操作

HTML 表单用于搜集不同类型的用户输入。 表单是一个包含表单元素的区域。 表单元素是允许用户在表单中输入内容,比如:文本域(textarea)、下拉列表、...

894
来自专栏高爽的专栏

Flex事件机制(一)

Flex事件贯穿我们整个开发,事件分为两类,用户事件和系统事件,比如说我们在页面点击了一个按钮,这是用户触发的事件,当组件初始化完毕,会触发creationC...

1910
来自专栏宋凯伦的技术小栈

Angular JS + Express JS入门搭建网站

  3月份开始,接到了新的任务,跟UI开发有关,用的是Angular JS,Express JS等技术。于是周末顺便学习下新技术。   组里产品UI架构如下: ...

2526
来自专栏前端人人

React多页面应用1(​webpack开发环境搭建,包括Babel、热更新等)

本教程总共7篇,每日更新一篇,请关注我们,敬请期待! 1.React多页面应用1(webpack开发环境搭建,包括Babel、热更新等) ----2017....

4156
来自专栏DeveWork

添加WordPress评论输入邮箱实时显示Gravatar头像功能

这个不是什么新鲜的功能了,这个功能即是实现当留言评论时,你输入email后,就会实时显示你的Gravatar头像。对于提高用户体验是有非常的帮助,特别是用户评论...

1965
来自专栏前端杂货铺

iframe编程的一些问题

前几天做一个用iframe显示曲线图的demo,发现对iframe的contentDocument绑定 onclick事件都无效,而在页面中对iframe.co...

3136

扫码关注云+社区