生命不息,折腾不止。
起因
最近上传了个背景图,加载的非常慢,才发现上传了个1M多的图。优化手段无非就是做做图片裁剪已经质量压缩,网上确实也有不少的分析压缩的方法,但基本都是jpeg和png等。偶然发现最近流行的WebP格式,又是对图片压缩的一大进步,可以大幅优化流量。
WebP就不多做介绍了,有兴趣的百度之。总之这个格式比等质量的png和jpg图片要小不少。但是作为浏览器的通病,各个浏览器未必能够支持,据介绍当前chrome和opera已经支持了,IE系肯定暂时没有支持。要使用这种图片看来得做适配,大致我搜索到的有两种方法:
- 采用插件支持,让页面支持WebP格式的解码(应该是通过flash)
- 采用HTML通过picture标记实现两种图片加载
- 懒加载,通过JavaScript控制加载的资源类型
以上方式是客户端常用的方式,不过像第二种方式需要刻意去修改HTML源码不是很方便,其他方式还行。当然除了上述方式外,还有一些在服务端可以处理的办法,首先是我根据实际测试总结出来的。
nginx处理方法
一般来讲,浏览器在请求服务端时候会携带支持的格式,目前支持webp的浏览器都会在请求Accept中携带 image/webp
,这是最简单的服务端检测方法,但是,总不能在代码中去干这个事情吧,况且本站还是静态博客。这个时候想到了牛逼的nginx,nginx有丰富的插件,在不了解有没有类似的插件的情况下完全可以去写一个。使用类似rewrite的功能去跳转。
查询资料发现应该可以通过nginx配置try_files加正则表达式的方式搞定,但是对nginx这块语法不是特别熟练外加配置写的一直不正确,暂时用nginx的lua插件测试下。需要准备一个正常图片如1.png,另外生成对应的webp格式如1.png.webp,统一访问webp资源。nginx根据Accept进行判断是否支持WebP,如果不支持跳转到非webp版本,即去掉webp后缀即可。
默认安装的nginx是没有lua功能的,需要单独编译,这里我偷懒直接使用老罗捐助过的 OpenResty
。在CentOS下可以直接添加repo进行yum安装,详情参见http://openresty.org/cn/linux-packages.html,安装完成之后,配置 /usr/local/openresty/nginx/conf/nginx.conf
,在location下添加类似如下代码(其实是一段lua)
rewrite_by_lua_block { |
其他根据实际需要配置。配置完成并启动nginx之后,写一个测试工程 test.html
及 test.jpg
和 test.jpg.webp
资源并部署到html目录。
<html> |
除了上面笨拙的办法,Google大神们还提供了个pagespeed模块。这个模块甚是强大,可以对网页进行速度优化,比如合并CSS,压缩空白,合并javascript等等,当然在支持webp的浏览器上会直接返回webp格式,更牛逼的是此过程是自动化的(包括webp格式的生成),不需要人为处理。
PageSpeed模块官网 https://developers.google.com/speed/pagespeed/module/
当然也是需要重新编译nginx的,并且在nginx配置中启用该功能
启用ngx_pagespeed |
启用之后速度杠杠的,当然据说(想想也是)副作用就是服务端的CPU和内存也很高,有点得不偿失。
本站方案
本站是hexo静态博客,主要的大图片在markdown博客中,我打算采用picture标记的方式实现,picture标记的思路是采用H5的picture标记来设置图片资源,如
<picture class="picture"> |
如果浏览器支持WebP格式则加载 image.jpg.webp
,否则加载image.jpg
。那么首先就是需要将hexo生成的代码修改为生成如上代码的方式。hexo采用的是marked引擎,好在修改比较简单,打开目录下 node_modules/marked/lib/marked.js
,找到 Renderer.prototype.image
函数实现,修改为以下版本
Renderer.prototype.image = function(href, title, text) { |
当然和之前一样,约定我们写markdown文档时候设置的图片是webp格式的,同时保留原始图片,如 1.png
和 1.png.webp
。这样修改之后,hexo生成出来的代码可以根据markdown里面的图片进行适配。
剩下的问题就是样式问题了,如果有特别的图像样式,需要修改原来的主题中的img样式进行迁移。将原来的img样式迁移到 .image
。因为我是博客文章中使用基本没什么问题,如果要完全使用,还需要注意CSS设置的图片(如背景图片)并不能自适应,请注意!
背景图片
如上在CSS中无法处理实现,在Hexo博客中采用的框架模式,那么进行统一的框架处理即可,但是WebP的支持情况就是在浏览器端才可以确认,因此在页面框架中增加一段加载完成后执行的JavaScript代码,用来检测和设置背景图片。
var side = document.getElementsByClassName("panel-cover")[0]; |
当然,具体的图片是在框架中根据配置生成的,大致原理如此,基本可以实现全站大图的WebP支持,当然小图片太多的话并且这么设置的话还是非常麻烦的,使用原始的格式即可。