当前位置: 首页 > 科技观察

如何优化移动端的图片流量

时间:2023-03-15 08:45:17 科技观察

刷新页面消耗的流量不是脚本样式文件,大部分其实都是下载的图片。一张图片动辄几十K,千方百计优化样式和脚本文件优化出来的图片流量其实还不如一张图片大。本文从两个角度介绍如何优化图片流量。本文图片流量优化的前提是针对移动端。Webp首先从图片格式开始。webp(google官网)是google推出的一种图片格式。优点是在同等画质下,体积比jpg、png小25%以上。以两张jpg和png图片为例:JPGhttp://cdn1.showjoy.com/images/c9/c9c2221942774550ad53342da23774de.jpgPNGhttp://cdn1.showjoy.com/images/bb/bb1c8b0d275e4ba2903dc822a03add50.pngsizeJPGPNGNone压缩165kb55kbtinypng压缩75kb20kbwebp转换54kb6.1kb从表中列表可以看出,压缩后的图片尺寸比tinypng小,图片质量甚至比tinypng还要高压缩。webp格式的图片虽然比png、jpg格式的图片体积更小,质量更高,但目前在全球范围内的兼容性只达到了70%左右。(caniuseasof20160911)据caniuse介绍,目前支持所有4.4以上的手机Android机型,但是ios彻底被淘汰了。我们的用户ios和Android分成了55%,webp的支持可以给至少一半的用户提供更小的图片体验。而且据说ios10系统会支持webp,所以我们产品的webp支持会更高。ios10有望支持webp图片服务器支持webp转换我公司原来有基于nginx+lua+graphicsmagick的图片缩略图功能,具体使用方法类似http://cdn1.shwojoy.com/images/34/xxxxx.pnghttp://cdn1.shwojoy.com/images/34/xxxxx.png.300x300.png为了支持webp转换,需要修改原来的lua脚本,增加.webp后缀的识别。使其能够识别和转换域名,如xxxxx.png.300x300.png.webp或xxxxx.png.webp。nginx+lua+graphicsmagick方案其实做的是nginx拦截域名,lua脚本匹配域名后缀规则,比如300x300.png/.webp类似的后缀,匹配完成后,在lua中调用graphicsmagick命令执行一些图像转换、裁剪等工作。lua脚本片段iftable.isLegal(size_list)andextend=="webp"thencommand=[[/usr/local/GraphicsMagick-1.3.25/bin/gmconvert-quality75-density72+profile"*"]]..ngx.var。image_root..originalUri.."-geometry"..area.."..ngx.var.file;os.execute(command);end值得注意的是graphicsmagick1.3.20及以上版本只支持webp下载graphicsmagick转换webp还需要下载并编译libwebp。graphicsmagick支持webp教程。图片服务器支持webp转换后,可以实时转换webp格式的图片,为下一步的webp兼容方案提供技术支持。http://cdn1.showjoy.com/images/c9/c9c2221942774550ad53342da23774de.jpghttp://cdn1.showjoy.com/images/c9/c9c2221942774550ad53342da23774de.jpg.webpwebp兼容方案目前判断浏览器端是否支持webp***该方法为特征检测法。根据检测结果,cookie中保存是否支持webp的值,用于后面需要判断webp兼容性的地方。特征检测脚本:(reference);(function(doc){//在html根节点添加webps类名functionaddRootTag(){doc.documentElement.className+="webpa";}//判断是否有webp_showjoy=availablecookieif(!/webp_showjoy=available/.test(document.cookie)){varimage=newImage();//图片加载时的操作image.onload=function(){//图片加载成功,宽度为1,那么说明支持webp,因为这个base64图片是webp格式的。如果不支持,会触发image.error方法if(image.width==1){//html根节点添加class,嵌入cookieaddRootTag();document.cookie="webp_showjoy=available;max-age=31536000;domain=";}};//一张支持alpha透明的webp图片,使用base64编码image.src='data:image/webp;base64,UklGRkoAAABXRUJQVlA4WAoAAAAQAAAAAAAAAAAAQUxQSAwAAAAARBxAR/Q9ERP8DAABWUDggGAAAABQBAJ0BQKgEAAQAAAP4AAAel)==(AAP7};}}(文档));如果浏览器支持webp格式的图片,在cookie中设置flag,在html标签上设置webpaclassName。这个classname的作用是兼容less文件中的webp图片。less文件中的webp兼容.webpbg(@url){background-image:url(@url);.webpa&{background-image:url('@{url}.webp');}}这个less替换原来在less文件中描述了背景图片的代码。比如之前定义的背景图片div{background-image:url(xx);}现在使用兼容方案:div{webpbg(xxx);}html文件中的webp图片兼容我们现在编写的html部分javavelocity,对于webp同步投递到页面的图片,会通过以下方式进行兼容。$!{isWebp}变量是通过判断浏览后台服务器请求的cookie中是否有之前定义的webp_showjoy=available,如果有则返回.webp后缀,如果没有则返回空。这样就有一个问题,用户第一次浏览商品页面时,后台判断cookie一直是false,所以用户第一次返回.webp后缀的图片是不可能的。另一种情况是,当图片被大量使用时,我们会使用懒加载来延迟图片的加载。这时候可以修改懒加载插件,动态兼容插件中的webp图片。/*根据cookie,返回图片是否为webp的地址*/functiongetwebpsrc(imgsrc){varneedwebp=false,src='';if(/webp_showjoy=available/.test(document.cookie)){needwebp=true;}src=needwebp?imgsrc+'.webp':imgsrc;returnsrc;}这样就完成了移动端对webp格式图片的支持。这也是图片流量优化的方案之一。Retina-compatibleimageflowoptimizationfront-ends应该都知道在retina屏幕下应该使用@2x或者@3x放大倍率的图片,以保证图片的清晰度。但有些公司为了切图方便,在切图阶段会统一切出@2x图片,无论浏览设备是retina屏还是普通屏,都会使用所有@2x图片。这样做有两个缺点。一是@2x图像在非视网膜屏幕上会出现缩减采样。虽然不会影响清晰度,但是会缺少一些锐度。二是@2x图片比@1x图片大,造成流量浪费,影响页面打开性能。所以正确的处理方式是是否为视网膜屏幕使用不同尺寸的图片。图像裁剪已在图像服务器上实现。在考虑retina的时候,还需要加上webp的兼容性,两者结合会大大减小图片的体积。@2xhttp://cdn1.showjoy.com/images/bb/bb1c8b0d275e4ba2903dc822a03add50.png.300x300.png.webp@1xhttp://cdn1.showjoy.com/images/bb/bb1c8b0d275e4ba2903dc822a03add50.png.150x15兼容视网膜文件retinabg(@file-2x;@reg-2x;@reg-1x;@type)when(isstring(@reg-2x)){background-image:url("@{file-2x}.@{reg-1x}.@{type}");.webpa&{background-image:url('@{file-2x}.@{reg-1x}.@{type}.webp');}@mediaonlyscreenand(-webkit-min-device-pixel-ratio:2),onlyscreenand(min--moz-device-pixel-ratio:2),onlyscreenand(-o-min-device-pixel-ratio:2/1),onlyscreenand(min-device-像素比:2),onlyscreenand(min-resolution:192dpi),onlyscreenand(min-resolution:2dppx){background-image:url("@{file-2x}.@{reg-2x}.@{type}");.webpa&{background-image:url('@{file-2x}.@{reg-2x}.@{type}.webp');}}}替换原来的背景图片:url(),可以这样写:.retinabg(http://cdn1.showjoy.com/images/bb/bb1c8b0d275e4ba2903dc822a03add50.png;300x300;150x150;png)html文件兼容retina,这个project已准备好在htmlht中使用ml5特性srcset属性secset属性的作用是让开发者可以为一张图片的属性指定一系列的来源,其中这些图片的来源要根据客户端显示屏幕的像素分辨率来设置。例如在volecity模板中定义图片资源:这个图像定义表明在视网膜(2x)屏幕下使用300x300的图像源,而在非视网膜屏幕(1x)使用150x150图像。html中的懒加载图片会在插件中对懒加载图片进行src赋值,所以直接在懒加载插件中根据window.devicePixelRatio判断修改图片url。/*根据cookie,返回图片是否为webp的地址*//*根据dpr返回不同大小的图片*/functiongetwebpsrc(imgsrc){varareaInfo='';if(window.devicePixelRatio&&window.devicePixelRatio<=1){vararea=imgsrc.match(/[0-9]+x[0-9]+/);if(area){varareaSplit=area[0].split('x');areaInfo=areaSplit[0]/2+'x'+areaSplit[1]/2;imgsrc=imgsrc.replace(/[0-9]+x[0-9]+/,areaInfo)}}varneedwebp=false,src='';if(/webp_showjoy=available/.test(document.cookie)){needwebp=true;}src=needwebp?imgsrc+'.webp':imgsrc;returnsrc;}在这个scheme下,所有的图片都要写一个size后缀(_num_x_num_),在我们公司的图片服务器的支持下,还有一个特别的好处:图片服务器会对带有size后缀的图片进行裁剪,同时对图片进行压缩。遇到不支持webp格式的浏览器,会顺便压缩图片。减小图像尺寸。srcset属性目前在移动端的兼容性很好,Android4.x版本不支持。总结一共两种图片流量优化方案,一种针对webp图片格式,一种针对retina。***写图片代码有三种场景:html同步图片写懒加载图片写法less.retinabg(http://cdn1.showjoy.com/images/bb/bb1c8b0d275e4ba2903dc822a03add50.png;300x300;150x150;png)webpbg(http://cdn1.showjoy.com/images/bb/bb1c8b0d275e4ba2903dc822a03add50.png);对我上面的理解有什么问题或者意见欢迎私聊~微博-写前端Siam