分块加载技术
与传统Ajax比较
一句话:分块加载技术
不利于SEO搜索引擎(这个说的不太对,可以采用其他手动弥补的)
一个重新设计的基础动态网页服务体系。
大体思路是,分解网页成叫做Pagelets的小块,然后通过Web服务器和浏览器建立管道并管理他们在不同阶段的运行。
不需要改变现有的网络浏览器或服务器,它完全使用PHP和JavaScript来实现。(此处是错误的,任何语言都可以实现)
HTTP 1.1引入分块传输编码
注:HTTP分块传输编码允许服务器为动态生成的内容维持HTTP持久链接。
HTTP分块传输编码格式
Transfer-Encoding: chunked 如果一个HTTP消息(请求消息或应答消息)的Transfer-Encoding消息头的值为chunked,那么,消息体由数量未定的块组成,并以最后一个大小为0的块为结束。
Nodejs自动开启 chunked encoding
除非通过sendHeader()设置Content-Length头。
'use strict'
var http = require('http')
const sleep = ms => new Promise(r => setTimeout(r, ms))
var app = http.createServer((req, res) => {
res.writeHead(200, { 'Content-Type': 'text/html', 'charset': 'utf-8' })
res.write('loading...<br>')
return sleep(2000).then(function() {
res.write(`timer: 2000ms<br>`)
return sleep(5000)
})
.then(function() {
res.write(`timer: 5000ms<br>`)
}).then(function() {
res.end()
})
})
app.listen(3000)
res.write('xxxx');
res.write('xxxx');
res.write('xxxx');
res.end('xxxx');
'use strict'
const sleep = ms => new Promise(r => setTimeout(r, ms))
var express = require('express')
var app = express()
app.get('/', function (req, res) {
res.type('html');
res.write('loading...<br>')
return sleep(2000).then(function() {
res.write(`timer: 2000ms<br>`)
return sleep(5000)
})
.then(function() {
res.write(`timer: 5000ms<br>`)
}).then(function() {
res.end()
})
})
app.listen(3000)
为什么不用res.send?
因为res.send包括了res.write()和res.end()
Koa里没有提供对bigpipe的支持,ctx.body赋值做了很多约定。可以说是不太容易控制。
在Koa里有2个概念非常容易混,req和request,res和response,我们经常在express里用req和res,但在Koa里它们指的是http启动server时传入的req和res参数
var http = require("http");
http.createServer((req, res) => {
res.writeHead(200, {
"Content-Type": "text/plain"
});
res.write("Hello World");
res.end();
}).listen(8888);
那么是不是可以不用Koa的东西,改用http的接口呢?res.write和express里的res.write是一样的。
var koa = require('koa')
var app = koa()
var co = require('co')
const Readable = require('stream').Readable
const sleep = ms => new Promise(r => setTimeout(r, ms))
app.use(function* () {
const view = new Readable()
view._read = () => { }
this.body = view
this.type = 'html'
this.status = 200
view.push('loading...<br>')
co(function* () {
yield sleep(2000)
view.push(`timer: 2000ms<br>`)
yield sleep(5000)
view.push(`timer: 5000ms<br>`)
/** 结束传送 */
view.push(null)
}).catch(e => { })
})
app.listen(9092)
const Koa = require('koa')
const app = new Koa()
const sleep = ms => new Promise(r => setTimeout(r, ms))
app.use(require('koa-bigpipe'))
// response
app.use(ctx => {
// ctx.body = 'Hello Koa'
ctx.write('loading...<br>')
return sleep(2000).then(function(){
ctx.write(`timer: 2000ms<br>`)
return sleep(5000)
}).then(function(){
ctx.write(`timer: 5000ms<br>`)
}).then(function(){
ctx.end()
})
})
app.listen(3000)
为什么是按照顺序加载的,怎么能并发加载呢?
自行领悟
注意!
分块加载的样式和脚本的加载顺序问题:
1. 第一次同步给浏览器的内容里如果包含样式和脚本,浏览器会立即请求
2. 后续的块状内容异步给浏览器后,对应的模块渲染完成,会立即请求模块里的样式文件
3. 上面第二种情况对js不起作用,浏览器只会渲染,不会做请求!!why??