图片通常是移动端网页中最占流量的资源。在很多类型的网站中(比如电商、社区),图片占据了网页的大部分空间。优化图片的质量和加载速度成为提高用户体验的重要途径。

传统方案的弊端

目前有一些被广泛应用的方案,例如选择压缩比更高的图片格式、使用雪碧图、HTTP2、CDN等。5年前的一条知乎回答前端开发中,对图片的优化技巧有哪些? - 贺师俊的回答 - 知乎现在依然有效,这些方案在各大网站中仍然发挥着重要的作用。

随着移动端兴起,各种移动设备带来了丰富的机型尺寸和像素密度,逐渐暴露出以上方案共同的问题,即都是基于网站粒度的通用方案。我们无法保证在每种机型上都达到最优的效果,只能通过一些取舍来达到较均衡的方案,从而满足大部分用户的体验需求。(虽然通过Media Query等方式可以对不同的屏幕进行一定程度的定制,但粒度较粗且功能有限,书写起来也比较复杂。)

传统方案带来的弊端主要有:

  • 为了兼容旧版浏览器,使用新版浏览器的用户无法享受新技术带来的更优体验。(例如无法使用具有更高压缩比的WebP格式。)
  • 通常采用的2x图方案对小屏幕尺寸是一种浪费,而在三倍屏上效果又不够好。

追求用户体验的道路没有止境。为了解决第一个问题,一些CDN厂商开始提供自适应的WebP图片转换技术,针对支持WebP的浏览器提供WebP格式图片(例如花瓣网使用的又拍云CDN)。

而Service Worker作为PWA核心技术,为我们带来了一些新的思路。

Service Worker

Service Worker是一个注册在指定源和路径下的事件驱动Worker。它采用JavaScript控制关联的页面或者网站,拦截并修改访问和资源请求,细粒度地缓存资源。你可以完全控制应用在特定情形(最常见的情形是网络不可用)下的表现。MDN

下图是Service Worker的支持情况。移动端方面Android的支持度较好,iOS Safari从11.3版本开始支持。总体支持度在84%(受地域和目标用户群体等方面的因素,经过统计,我们产品的设备支持度为63%)。

Service Worker的具体使用方法这里不再赘述。接下来将重点介绍如何使用Service Worker对图片请求做更细粒度的控制,达到渐进式优化的目标。

使用WebP

WebP是一种新的图像格式,它为Web中的图像提供更好的无损压缩和有损压缩。使用WebP可以创建更小、更丰富的图像。
WebP无损图像的尺寸比PNG小26%,有损图像比相同SSIM指数的JPEG图像小25-34%。Google

下图是WebP的兼容性一览。作为Google提出的一项技术,WebP在Android端有很好的支持,但目前的兼容性还无法在移动端网页中广泛使用。默认情况下,我们仍然需要根据实际情况选用恰当的图片格式,在PNG/GIF/JPEG中进行取舍(例如,对于无透明度且色彩丰富的图片,通常会选用压缩比较高的JPEG格式)。

而在使用Service Worker的网站中,由于我们可以拦截和修改网络请求,因此可以针对支持WebP格式的浏览器,修改为请求对应的WebP图片链接;而在不支持的浏览器中依然请求原链接。从而达到向后兼容式的优化。

// sw.js
self.addEventListener('fetch', (event) => {
const req = event.request.clone()
let newUrl = req.url
if (!isImgRequest(newUrl)) {
return
}
// 如果浏览器支持webp格式,则请求webp格式的图片
const acceptHeader = req.headers.get('accept')
const supportWebp = acceptHeader && acceptHeader.includes('webp')
if (supportWebp) {
newUrl = getWebpUrl(newUrl)
}
// 请求处理过的图片链接
event.respondWith(
fetch(newUrl, {
mode: 'no-cors'
})
)
}) function isImgRequest(url) {
// 根据url判断当前是否是需要优化的图片请求
} function getWebpUrl(url) {
// 根据图片url获取到对应的webp格式url(一般的图片服务器都会提供获取图片格式转换参数)
}

有关DPI自适应的思考

对于使用rem方案来实现自适应布局的网站来说,图片的展示宽高也会根据实际情况进行缩放。但由于图片通常采用固定的实际尺寸(例如使用2x图),当图片被缩放时,在小屏幕上会产生浪费,在大屏中效果却被打了折扣。如果我们能够根据不同机型,获取匹配实际物理分辨率的图片进行展示,则可针对每种设备最大程度的优化用户体验。

假设网站使用的图片存储服务提供了针对图片的缩放接口(例如,图片https://domain/key可以通过添加参数来将宽/高像素数减少到原来的0.6倍:https://domain/key/thumbnail/!60p)。针对支持Service Worker的浏览器,就可以根据设备的分辨率修改图片请求的缩放参数,从而达到设备粒度的图片尺寸定制。

这里需要注意的是Service Worker作为一种特殊的Worker不能直接操作DOM,全局作用域(通过self关键字访问)上也只有部分和window对象相同的属性和方法。因此我们需要通过Service Worker与网页之间的通信来获取到当前设备的屏幕尺寸和DPI等信息。代码示例如下:

// 网页代码
navigator.serviceWorker.controller.postMessage({ deviceWidth: window.screen.width * window.devicePixelRatio }) // sw.js
const TRIPLE_PIXEL = 1242 // 3x横向像素数
let deviceWidth = 0 self.addEventListener('fetch', (event) => {
const req = event.request.clone()
let newUrl = req.url
if (!isImgRequest(newUrl)) {
return
}
// 如果有屏幕分辨率信息,为请求url添加缩放参数
if (deviceWidth) {
const ratio = Math.round(deviceWidth / TRIPLE_PIXEL * 100)
if (ratio > 0 && ratio < 100) {
newUrl = getThumbnailUrl(newUrl, ratio)
}
}
// 请求处理过的图片链接
event.respondWith(
fetch(newUrl, {
mode: 'no-cors'
})
)
}) self.addEventListener('message', ({ data }) => {
deviceWidth = data.deviceWidth
}) function getThumbnailUrl(url, ratio) {
// 返回添加缩放参数的图片url
}

除了使用缩放参数,我们也可以分别导出1x/2x/3x图(默认使用2x图),根据DPI信息将图片请求替换为对应的<n>x图即可。

总结

Service Worker的功能如此强大,目前常用的情形已经有离线访问、构建App Shell等。期待未来Service Worker以及其它PWA技术能够不断带给我们新的思路。

PWA 时代的移动端图片优化新思路的更多相关文章

  1. 前端性能和加载体验优化实践(附:PWA、离线包、内存优化、预渲染)

    一.背景:页面为何会卡? 1.1 等待时间长(性能) 项目本身包/第三方脚本比较大. JavaScript 执行阻塞页面加载. 图片体积大且多. 特别是对于首屏资源加载中的白屏时间,用户等待的时间就越 ...

  2. 美图App的移动端DNS优化实践:HTTPS请求耗时减小近半

    本文引用了颜向群发表于高可用架构公众号上的文章<聊聊HTTPS环境DNS优化:美图App请求耗时节约近半案例>的部分内容,感谢原作者. 1.引言 移动互联网时代,APP 厂商之间的竞争非常 ...

  3. 如何处理 Web 图片优化?

    未优化的图片是影响网站性能的主要因素之一,尤其会影响初次加载.取决于图像的分辨率和画质,图片可能占据整个网站流量的 70%. 生产环境出现未优化的图片并显著影响初次加载速度的现象还是挺常见的.缺乏经验 ...

  4. Web性能优化:图片优化

    程序员都是懒孩子,想直接看自动优化的点:传送门 我自己的Blog:http://cabbit.me/web-image-optimization/ HTTP Archieve有个统计,图片内容已经占到 ...

  5. HTML5移动端图片左右切换动画

    插件描述:HTML5移动端图片左右切换动画 小海今天要给大家分享一款很不错的图片左右切换焦点图动画,并且支持移动端触摸滑动.功能上,这款HTML5图片播放器支持鼠标滑动.手机端触摸滑动以及自动播放.外 ...

  6. 移动端图片上传解决方案localResizeIMG先压缩后ajax无刷新上传

    现在科技太发达,移动设备像素越来越高,随便一张照片2M+,但是要做移动端图片上传和pc上略有不同,移动端你不能去限制图片大小,让用户先处理图片再上传,这样不现实.所以理解的解决方案就是在上传先进行图片 ...

  7. 移动端网站优化指南-WAP篇

    转载:http://seofangfa.com/mobile-seo/mobile-seo-guide.html 1.域名优化:启用短域名,例如:m.abc.com,便于用户记忆,方便搜索蜘蛛查找,减 ...

  8. Web前端性能优化之图片优化

    我自己的Blog:http://blog.cabbit.me/web-image-optimization/ HTTP Archieve有个统计,图片内容已经占到了互联网内容总量的62%,也就是说超过 ...

  9. 浅谈CSS样式png、gif、jpg图片优化的方法

    一.PNG.GIF.JPG图片对比 在我们进行图像优化技术前,需要学习有关的图片格式的一些技术细节,每个图形格式都有自己的优势和拖弱点,知道他们会使你得到更好的视觉质量和压缩品质. 网页图片优化是网页 ...

随机推荐

  1. Mac Mini 安装Ubuntu20.04 KVM

    在一台 Mac Mini mid 2011上安装Ubuntu20.04并配置KVM环境, 过程也适用于其他版本的Mac Mini. 硬件配置 I5 2415, 内存8G*2, 硬盘 SSD 500G ...

  2. MySQL之InnoDB存储引擎 - 读书笔记

    1. MySQL 的存储引擎 MySQL 数据库的一大特色是有插件式存储引擎概念.日常使用频率最高的两种存储引擎: InnoDB 存储引擎支持事务,其特点是行锁设计.支持外键.非锁定读(默认读取操作不 ...

  3. Pycharm:如果想验证一个文件中的函数

    在该文件的函数后写上两句 def test(): pass if __name__='__main__': test() 这样就可以执行该函数 如果只是在其他文件中导入了该函数,则不会执行最后两段话, ...

  4. CSDN中Markdown编辑器使用方法

    Markdown编辑器 如果想学习如何使用Markdown编辑器, 可以仔细阅读这篇文章,了解一下Markdown的基本语法知识. 新的改变 CSDN中Markdown编辑器进行了一些功能拓展与语法支 ...

  5. JZ-052-正则表达式匹配

    正则表达式匹配 题目描述 请实现一个函数用来匹配包括'.'和''的正则表达式.模式中的字符'.'表示任意一个字符,而''表示它前面的字符可以出现任意次(包含0次). 在本题中,匹配是指字符串的所有字符 ...

  6. numpy: np.logical_and/or/not (逻辑与/或/非)+python3-曲线拟合(polyfit/polyval)

    可以用拟合两个变量之间的关系,然后根据一个变量,去推测出另外一个变量的推测值

  7. CF1117G题解

    题意:区间建笛卡尔树,求每个节点的siz之和. 首先看到笛卡尔树,就应该想到,因为这是一个排列,可以找到通过左边和右边第一个比自己大的元素来"建立"笛卡尔树. 设 \(l(u)\) ...

  8. 跨平台跨架构的统信DTK开发套件教程及常见问题

    DTK是统信基于Qt开发的一整套简单且实用的通用开发框架,处于统信UOS系统中的核心位置,统信UOS浏览器.音乐.邮件等40余款原生应用全部使用DTK开发.DTK从开发者的角度出发,融合现代化的开发理 ...

  9. Java基础——引用类型作为形参与返回值

    一.具体类名作为形参与返回值 1.方法的形参是类名,其实需要的是该类的对象 比如有一个具体的猫类,我使用另一个类使用猫类的方法 public class CatOperator {   public ...

  10. 配置 PackMan 镜像

    一.参考链接 阿里云镜像站 二.PackMan 镜像介绍 Packman 是 OpenSUSE 最大的第三方软件源,主要为 OpenSUSE 提供额外的软件包,包括音视频解码器.多媒体应用.游戏等. ...