You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
对比美团首页的特征检测,两者基本一样,只是在第一步判断 UA 上有点不同。至少安卓端上的UC浏览器(11.4.2.936)是支持 webp 的,而 iPad 的 UA又被剔除了,比较奇怪。
美团周边游webp替换可以分成两个部分
1.前端检测与替换。
! function() {
"use strict";
var i = function(i) {
var t = {};
if (i)
for (var e = 0, a = i.length; e < a; ++e) {
var n = i[e];
t[n.poiid] = n.ct_poi
}
return t
},
t = function(i) {
var t = {};
if (i)
for (var e = 0, a = i.length; e < a; ++e) {
var n = i[e];
t[n.dealid] = n.stid
}
return t
},
e = Math.PI / 180,
a = function(i, t) {
return i = Number(i),
t = Number(t),
function(a, n) {
var o, r, c = i * e,
u = a * e,
l = c - u,
g = t * e - n * e;
return c && u && l && g && (o = 12756274 * Math.asin(Math.sqrt(Math.pow(Math.sin(l / 2), 2) + Math.cos(c) * Math.cos(u) * Math.pow(Math.sin(g / 2), 2))),
r = Math.round(o),
r = r >= 100 ? Math.round(r / 100) / 10 : "0.1"),
r
}
},
n = function(t, e, n, o, r, c, u, l, g) {
if (e = i(e),
"distance" === o || r) {
r = r.split(",");
var p = a(r[0], r[1])
}
for (var d = 0, m = t.length; d < m; ++d) {
var s = t[d];
if (s.ct_poi = e[s.poiid],
s.frontImg && (s.img = s.frontImg.replace("w.h", "100.0"),
s.imgHigh = s.frontImg.replace("w.h", "200.0"),
n && (s.img += ".webp",
s.imgHigh += ".webp")),
g && (5 === s.avgScore ? s.score = 50 : s.avgScore >= 4.5 ? s.score = 45 : s.avgScore >= 4 ? s.score = 40 : s.avgScore >= 3.5 ? s.score = 35 : s.score = 10 * Math.floor(s.avgScore)),
s.iconCount = 0,
s.poiTags)
for (var h = s.poiTags.split(","), f = 0; f < h.length; f++) {
var v = h[f];
if ("MP" == v)
s.MP = 1,
s.iconCount++;
else if ("ZTC" == v) {
if (g)
continue;
s.ZTC = 1,
s.iconCount++
} else if ("TC" == v) {
if (g)
continue;
s.TC = 1,
s.iconCount++,
s.iconCount++
} else if ("LINE" == v) {
if (g)
continue;
s.LINE = 1,
s.iconCount++
} else
"GROUP" == v ? (s.GROUP = 1,
s.iconCount++) : "MYY" == v ? s.MYY = 1 : "BTT" == v && (s.BTT = 1)
}
if ("android" == u || "iphone" == u ? s.url = "imeituan://www.meituan.com/poi?channel=travel&id=" + s.poiid : "zhoubianyou" == l ? s.url = (g ? "//m.dianping.com/shop/" : "/awp/h5/lvyou/poi/detail/index.html?poiId=") + s.poiid + "&ct_poi=" + s.ct_poi : s.url = "/poi/" + s.poiid,
("distance" === o || p) && s.lat && s.lng) {
var M = [];
M.push(p(s.lat, s.lng));
var w = Math.min.apply(Math, M);
w && "zhoubianyou" == l && (s.areaName = w + "km")
}
}
return t
},
o = function(i, e, n, o, r, c, u, l) {
if (e = t(e),
"distance" === o || r) {
r = r.split(",");
var g = a(r[0], r[1])
}
for (var p = 0, d = i.length; p < d; ++p) {
var m = i[p];
if (m.stid = e[m.id],
m.image = m.squareimgurl || m.frontImg,
m.image && (m.img = m.image.replace("w.h", "100.0"),
m.imgHigh = m.image.replace("w.h", "200.0"),
n && (m.img += ".webp",
m.imgHigh += ".webp"),
delete m.image),
("distance" === o || g) && m.mlls) {
var s = m.mlls.split(";");
if (s.length) {
for (var h = [], f = 0; f < s.length; f++) {
var v = s[f].split(",");
h.push(g(v[0], v[1]))
}
var M = Math.min.apply(Math, h);
M && (m.areaName = M + "km")
}
}
"android" == u || "iphone" == u ? m.url = "imeituan://www.meituan.com/deal?channel=travel&did=" + m.id : m.url = "/deal/" + m.id + ".html"
}
return i
},
r = function(i, t, e, a, r) {
if (!i || !i.data || i.data && !i.data.length)
return {};
var c, u = {},
l = !1;
return e = e || {},
a = a || "deal",
r = r || "",
l = "dp" == t.get("source"),
u.isRecommend = i.isRecommend,
"poi" == a && (i.count ? u.count = i.count : u.count = i.data.length,
u.tj = i.ct_pois,
c = n),
"deal" == a && (i.paging && i.paging.count ? u.count = i.paging.count : u.count = i.data.length,
u.tj = i.stids,
c = o),
u.list = c(i.data, u.tj, e.webp, t.get("sort"), t.get("mypos"), t.get("cateId"), t.get("utm_medium"), r, l),
u
};
"object" == typeof exports ? module.exports = r : define(function() {
return r
})
}();
目前,对于启用 webp 图片比较普遍的做法都是通过前端进行特征检测,根据检测结果,替换图片链接地址。下面看一种别的方法: 利用 Service Workers 动态响应 webp
// Register the service worker
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/service-worker.js').then(function(registration) {
// Registration was successful
console.log('ServiceWorker registration successful with scope: ', registration.scope);
}).catch(function(err) {
// registration failed :(
console.log('ServiceWorker registration failed: ', err);
});
}
// service-worker.js
"use strict";
// Listen to fetch events
self.addEventListener('fetch', function(event) {
// Check if the image is a jpeg
if (/\.jpg$|.png$/.test(event.request.url)) {
// Inspect the accept header for WebP support
var supportsWebp = false;
if (event.request.headers.has('accept')) {
supportsWebp = event.request.headers.get('accept').includes('webp');
}
// If we support WebP
if (supportsWebp) {
// Clone the request
var req = event.request.clone();
// Build the return URL
var returnUrl = req.url.substr(0, req.url.lastIndexOf(".")) + ".webp";
event.respondWith(
fetch(returnUrl, {
mode: 'no-cors'
})
);
}
}
});
webp的一些事儿
前言
webp
是 google 推出的一种支持无损、有损压缩的一种格式,详情可以看这儿 webp图片使用方案预研 ,这儿WebP 探寻之路 ,还有这儿 google官方文档 (需翻~墙)。它的优点在于,一般情况下下,
webp
格式的图片体积会比png
,jpg
格式的图片体积小,体积小就可以节省流量,提高加载速度,增强用户体验,体积小就是给公司节约 money。 目前,很多公司都已经启用了webp
,下面就看哈他们是怎么做的。以h5
页面为例,app
端的webp
支持需要单独的解析库,这儿不做讨论。京东
京东的首页(m.jd.com)没有启用
webp
,但是在 京东超市 服装城 等页面,都启用了webp
。以京东超市为例:
京东超市首屏
在禁用
js
的情况下,可以看到,京东超市只加载了部分结构,对于图片,则通过js
控制进行图片懒加载,通过查看网页源代码可以发现,首屏的图片懒加载由立即执行函数控制,如下图:立即执行函数
通过格式化该函数可以发现,该函数对
webp
进行了特性检测:通过执行
run()
函数,调用_webpDetect()
检测用户浏览器对webp
的支持情况,对于支持webp
的,把对象的isWebpSupported
属性设置为真,之后执行_main()
函数,而在_main()
函数中,会通过执行_webpFormat()
函数,对支持webp
格式的浏览器页面进行格式化,即把懒加载的jpg png
图片地址加上.webp
,进而进行懒加载。京东超市首屏图片懒加载
对于页面中下部,模板懒加载的部分,则会执行
main.js
文件中的webp
特征检测函数,执行逻辑则和前面的立即执行函数基本一致。从上面几张图片的
url
地址还可以发现,京东的图片支持分辨率和图片质量的控制,s2101x2101_jfs
为图片分辨率,q100
为图片压缩质量。美团
美团(i.meituan.com)首页有
webp
的特征检测,但是没有启用webp
图片。但美团的一些具体页面,都启用了webp
图片。美团首页
webp
特征检测。该代码会先检测浏览器UA
,对于是iPhone iPad
等属于iOS
系统的移动端浏览器,则直接将cookie
中的webp
记录设置比当前时间早一天的过期时间,即让该cookie
记录失效并删除该记录;对于非iOS
的浏览器,且cookie
中没有webp
记录的,则会执行一次特征检测,对支持webp
的浏览器会设置一年过期时间的webp
记录。这样可以方便其它页面进行判断。以美团周边游为例:
webp
特征检测代码:上述
webp
特征检测代码,对支持webp
的浏览器,会在cookie
中添加一个webp=1
记录(还包含过期时间等)。对比美团首页的特征检测,两者基本一样,只是在第一步判断
UA
上有点不同。至少安卓端上的UC浏览器(11.4.2.936)是支持webp
的,而iPad
的UA
又被剔除了,比较奇怪。美团周边游webp替换可以分成两个部分
1.前端检测与替换。
这一部分主要是在异步加载数据的部分。在结构懒加载时,会在支持
webp
的浏览器,添加.webp
结尾。而首屏加载的页面结构,进行图片懒加载时,图片继续保留原格式,并不会替换成webp
。2.后台检测与数据返回
首屏加载的页面数据,会在第二次访问时发生改变。当用户第二次及之后访问美团周边游页面时,后台服务器会根据
cookie
中的webp
记录,返回已经添加.webp
结尾的页面数据。美团周边游两次访问返回数据对比
天猫 淘宝
天猫和淘宝的
webp
也主要是利用特征检测,然后替换图片地址,这里就不展开叙述了。其他
目前,对于启用
webp
图片比较普遍的做法都是通过前端进行特征检测,根据检测结果,替换图片链接地址。下面看一种别的方法: 利用Service Workers
动态响应webp
先上代码再分析。上述代码先在页面上判断浏览器是否支持
service Worker
,支持的,注册并安装service-worker.js
。在service-worker.js
中,通过监听fetch
事件,如果是jpg png
的图片请求,则检测这些图片请求的请求头accept
字段,是否包含image/webp
字符串。如果有该字符串,表示浏览器支持webp
格式,进一步替换这些图片的url
地址。支持
webp
的浏览器图片请求不支持
webp
的浏览器图片请求通过
service Worker
的方法看上去不错,但是目前service Worker
的兼容性还比较差。因此,通过利用Service Workers
动态响应webp
的方法还难以用于生产环境。service workers 兼容情况
总结
综上,目前行业内启用
webp
的做法普遍以前端特性检测+替换图片地址为主,辅之以后后端检测输出。参考资料
欢迎批评指正 :)
PS:这是2017年4月做的一个
webp
小调研的总结The text was updated successfully, but these errors were encountered: