炫意html5
最早CSS3和HTML5移动技术网站之一

淘宝网性能优化之借鉴——webp及Bigpipe

前言

说到性能优化,我博客前面文章讲了不少,其实性能优化做的好坏,直接体现前端开发人员的水平。因此,很多面试中基本上都会提及这一点。今天主要借鉴淘宝网性能优化方式之一webp及Bigpipe 进行简单的讲解。

webp

打开淘宝网,假如你是chrome浏览器,你会发现,所有图片都是webp结尾的,淘宝网图片运用了webp。假如你是safari浏览器,看到图片就是jpg或者png了,淘宝网自动判断浏览器支持不支持webp,假如支持,则输出相应的图片格式!

看下图:

enter image description here

淘宝网图片请求头。

淘宝网的流程应该也是如下的:

运用了bigpipe客户端服务器端同时渲染,图片全是异步请求。

1、判断浏览器是否支持webp

2、客户端发送请求头到服务器端,假如请求头带:

image/webp,

说明支持webp ,则服务器渲染webp格式图片,否则就是jpg或者png

如何检测平台是否支持webp格式

方法一:

function checkWebp() {
try{
return (document.createElement('canvas').toDataURL('image/webp').indexOf('data:image/webp') == 0);
}catch(err) {
return  false;
}
}
console.log(checkWebp());   // true or false

方法二:自官网的。

// check_webp_feature:
//   'feature' can be one of 'lossy', 'lossless', 'alpha' or 'animation'.
//   'callback(feature, result)' will be passed back the detection result (in an asynchronous way!)
function check_webp_feature(feature, callback) {
var kTestImages = {
lossy: "UklGRiIAAABXRUJQVlA4IBYAAAAwAQCdASoBAAEADsD+JaQAA3AAAAAA",
lossless: "UklGRhoAAABXRUJQVlA4TA0AAAAvAAAAEAcQERGIiP4HAA==",
alpha: "UklGRkoAAABXRUJQVlA4WAoAAAAQAAAAAAAAAAAAQUxQSAwAAAARBxAR/Q9ERP8DAABWUDggGAAAABQBAJ0BKgEAAQAAAP4AAA3AAP7mtQAAAA==",
animation: "UklGRlIAAABXRUJQVlA4WAoAAAASAAAAAAAAAAAAQU5JTQYAAAD/////AABBTk1GJgAAAAAAAAAAAAAAAAAAAGQAAABWUDhMDQAAAC8AAAAQBxAREYiI/gcA"
};
var img = new Image();
img.onload = function () {
var result = (img.width > 0) && (img.height > 0);
callback(feature, result);
};
img.onerror = function () {
callback(feature, false);
};
img.src = "data:image/webp;base64," + kTestImages[feature];
}

其实跟第一种方法差不多,这里提供了几种webp的图片模式,如果浏览器支持webp,那么图片的宽高会大于0,从而返回true,否则返回false.

使用方法:

第一个参数feature可以传 lossy,lossless,alpha,animation中的一个,第一个传个回调函数。获取他result。如果支持,返回ture,否则返回false。可以再谷歌和IE下试试,谷歌返回ture,IE返回false

check_webp_feature('lossless',function(feature,result){
alert(result); //true or false
});

方法三:增加class

;(function(doc) {
// 给html根节点加上webps类名
function addRootTag() {
doc.documentElement.className += "webps";
}
// 判断是否有webps=A这个cookie
if (!/(^|;\s?)webps=A/.test(document.cookie)) {
var image = new Image();
// 图片加载完成时候的操作
image.onload = function() {
// 图片加载成功且宽度为1,那么就代表支持webp了,因为这张base64图是webp格式。如果不支持会触发image.error方法
if (image.width == 1) {
// html根节点添加class,并且埋入cookie
addRootTag();
document.cookie = "webps=A; max-age=31536000; domain=xyhtml5.com";
}
};
// 一张支持alpha透明度的webp的图片,使用base64编码
image.src = 'data:image/webp;base64,UklGRkoAAABXRUJQVlA4WAoAAAAQAAAAAAAAAAAAQUxQSAwAAAARBxAR/Q9ERP8DAABWUDggGAAAABQBAJ0BKgEAAQAAAP4AAA3AAP7mtQAAAA==';
} else {
addRootTag();
}
}(document));

原理也是一样的,不过这个比较贴近实战,就是加载一张webp图片,如果可以加载出来,那么就是支持webp,否则就是不支持。如果支持webp,那么给html加一个class 叫 webps。

方法四:

var isSupportWebp = !![].map && document.createElement('canvas').toDataURL('image/webp').indexOf('data:image/webp') == 0;

一行代码就可以判断浏览器支持不支持webp。

用法:

console.log(isSupportWebp);   // true or false

webp格式纯前端应用

这种方式只是纯前端的一种尝试,还是推荐和后端配合使用。

纯前端使用的话,可以如下方式:

在页面加载css之前,加载检测是否支持webp的js。如果支持,则html节点上里面有一名为webps的class。

背景图的话,我们就用写两套。一套是没有用webp的css,一套是用了webp图片的背景图。

.炫H5{
background-image: url('../images/炫H5.jpg');
}
.webps .炫H5{
background-image: url('../images/炫H5.webp');
}

img图片也是一样,用js输出相关路径。特别适用于异步加载。

Bigpipe 技术

也是比较早的前端渲染技术了,淘宝网用了,请看文章:http://taobaofed.org/blog/2016/03/25/seller-bigpipe-coding/

Bigpipe 技术是把网页分割成多个PageLet的小块,然后分段输出到浏览器,前后端并行处理。

BigPipe的原理

BigPipe的主要思想是实现浏览器和服务器的并发执行,实现页面的异步加载,从而提高页面的访问速度。
为了达到这个目的,它首先根据页面的功能或者位置,将页面分成若干个模块,这些模块的名字也被称为PageLet,并对这些分解的模块进行唯一的标识。然后通过Web服务器和浏览器之间建立管道,进行分段输出 (减少请求数)。

下面来看一个简单的例子:

我们来看下面的代码:layout.html

<!DOCTYPE html>
<html>
<head>
<script>
var BigPipe = {
view: function(selector,temp) {
document.querySelector(selector).innerHTML= temp;
}
}
</script>
</head>
<body>
<div></div>
<div></div>
<div></div>

服务端代码,基于express

var express = require('express');
var app = express();
var fs = require('fs');
app.get('/', function (req, res) {
var layoutHtml = fs.readFileSync(__dirname + "/layout.html").toString();
res.write(layoutHtml);
// setTimeout只是模拟异步返回
setTimeout(function() {
res.write('<script>BigPipe.view("#moduleA","moduleA");</script>');
100);
setTimeout(function() {
res.write('<script>BigPipe.view("#moduleC","moduleC");</script>');
},200);
setTimeout(function() {
res.write('<script>BigPipe.view("#moduleB","moduleB");</script>');
res.write('</body></html>');
},300);
res.end();
});
app.listen(3000);

关于Bigpipe,淘宝前端团队有2篇文章,讲的很细致,推荐大家一看:

1、http://taobaofed.org/blog/2016/03/25/seller-bigpipe-coding/

2、http://taobaofed.org/blog/2015/12/17/seller-bigpipe/

炫意HTML5 » 淘宝网性能优化之借鉴——webp及Bigpipe

Java基础教程Android基础教程