前不久新浪微博改版,前端引入了BigPipe(最早是Facebook提出的),页面载入速度嗖嗖嗖地上去了。。那末为神马BigPipe能这么快呢?
与AJAX相似,BigPipe使页面可以按区块渲染。但与AJAX不同的是,BigPipe不需要在页面载入后再通过XMLHttpRequest向服务器发起异步请求,而是(通过使用缓冲区)在页面载入过程中先输出页面布局,并在HTML中预留各个页面区块(Facebook称为Pagelet),在页面底部才输出Javascript代码,DOM操作,从而对区块进行内容填充,也就是把内容赋给innerHTML。
这么做的好处是,在页面加载的过程中,把一些响应时间相对较长的输出放到了页面底部,而页面整体轮廓先显示出来,减少用户的等待时间;此外,与Ajax相比,BigPipe不需要进行多次请求就能完全显示内容,降低了服务器的负担。
下面用PHP模拟一下BigPipe,代码里用sleep(1)模拟一些运算的时间损耗(要先关闭Apache的GZip):
<!doctype>
<html>
<head>
<meta charset="utf-8" />
<title>PHP模拟BigPipe</title>
</head>
<style>
.section{height:200px;}
#con1{background:#ef8090;}
#con2{background:#fef000;}
#con3{background:#19c000;}
</style>
<body>
<div class="wrapper">
<div class="section" id="con1">页头内容,正在加载……</div>
<div class="section" id="con2">正文内容,正在加载……</div>
<div class="section" id="con3">页尾内容,正在加载……</div>
</div>
<?php
/*
* 输出缓存区
*/
function flush_now(){
ob_flush();
flush();
}
flush_now();
?>
<?php sleep(1);?>
<script>
document.getElementById("con1").innerHTML = "<?php echo str_repeat(\'内容1\', 200) ?>";
</script>
<?php flush_now()?>
<?php sleep(1);?>
<script>
document.getElementById("con2").innerHTML = "<?php echo str_repeat(\'内容2\', 200) ?>";
</script>
<?php flush_now()?>
<?php sleep(1);?>
<script>
document.getElementById("con3").innerHTML = "<?php echo str_repeat(\'内容3\', 200) ?>";
</script>
<?php flush_now()?>
</body>
</html>
这样,打开页面后,页头、正文和页尾的内容一开始显示的是“正在加载……”,但随后内容会逐一显示出来,肿么样,很神奇吧。
但话说回来,这只是模拟的BigPipe,因为每个区块的内容输出之间是阻塞的,需要等待前一个区块处理完了,才能接着处理后一个。而要真正实现BigPipe就得使用多线程,可以通过CURL的异步模式或者pctnl。
近期评论