node網(wǎng)頁分段渲染詳解
頁面渲染,通常來說分為前端渲染以及后端渲染。前端渲染指的是服務端返回html框架以及模版,前端通過ajax異步請求拉取數(shù)據(jù)渲染模版,并動態(tài)修改dom,形成最終頁面。服務端渲染則是服務端通過在后端拉取數(shù)據(jù)以及后端模版渲完整頁面,并返回到客戶端。2種方法各有好處,后端渲染帶來的則是首屏時間的提高,減少請求次數(shù),利于SEO等好處。但是傳統(tǒng)后端直出渲染需要等到整個網(wǎng)頁渲染完成,才能返回到客戶端。假如某個區(qū)塊拉取數(shù)據(jù)比較慢,影響了渲染的速度,那對于用戶來說,等待的時候也會跟著變長對于后端渲染能否跟前端ajax渲染一樣,分塊分區(qū)域傳統(tǒng)的服務端直出渲染,下面將提供一種解決方案-網(wǎng)頁分段渲染。
首先我們先看下傳統(tǒng)的渲染方式:
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或者數(shù)據(jù)拉取。這個時候我們觀察返回頁面的時間是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 即開啟了分段傳輸?shù)哪ХāT摼幋a方式存在http1.1中,一般在服務器生成HTTP回應是無法確定信息大小的,這時用Content-Length就無法事先寫入長度,而需要實時生成消息長度,則服務器一般采用Chunked編碼。
在進行Chunked編碼傳輸時,在回復消息的頭部有transfer-coding并定義為Chunked,表示將用Chunked編碼傳輸內(nèi)容。 下面我們看下修改后的效果:
雖然總體的頁面?zhèn)鬏敃r間并沒有變化,但是通過該方式,我們將響應時間縮短了一半,減少了用戶等待的時間。在具體業(yè)務中,我們可以講用戶需要先看到的部分進行提前輸出,將后端處理耗時較久的部分延遲輸出,這就是分段傳輸渲染的優(yōu)勢。 注意如果服務器是nginx,有可能由于緩沖區(qū)的設置導致分段渲染無效,需要調(diào)整緩沖區(qū)大小。
相關文章
Node 搭建一個靜態(tài)資源服務器的實現(xiàn)
這篇文章主要介紹了Node 搭建一個靜態(tài)資源服務器的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2019-05-05node 利用進程通信實現(xiàn)Cluster共享內(nèi)存
本篇文章主要介紹了node 利用進程通信實現(xiàn)Cluster共享內(nèi)存,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-10-10node.js對于數(shù)據(jù)庫MySQL基本操作實例總結【增刪改查】
這篇文章主要介紹了node.js對于數(shù)據(jù)庫MySQL基本操作,結合實例形式總結分析了node.js針對mysql數(shù)據(jù)庫基本配置、連接與增刪改查相關操作技巧,需要的朋友可以參考下2023-04-04NodeJS學習筆記之(Url,QueryString,Path)模塊
今天我們來看一下在nodejs中路徑的相關操作方法。在我們開發(fā)過程中路徑主要有:URL路徑,在瀏覽器中進行使用,當然這個也包含查詢字符串QueryString的相關操作;而另一種是磁盤路徑,主要用于文件等等進行操作,我們稱為Path,所以我將它們放在一起進行總結學習。2015-01-01Nodejs + sequelize 實現(xiàn)增刪改查操作
這篇文章主要介紹了Nodejs + sequelize 實現(xiàn)增刪改查操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-11-11Node.js中使用mongoskin操作mongoDB實例
這篇文章主要介紹了Node.js中使用mongoskin操作mongoDB實例,Mongous是一個輕量級的nodejs mongodb驅(qū)動,需要的朋友可以參考下2014-09-09