本文旨在如何快速在vue项目上切换全站图片,并针对不兼容的浏览器版本进行降级。
生成webp
对于目前大多数的项目来说,比较方便且合适的方式是集成webpack的loader或者plugin,在build的过程中生成webp。当然也可以预先在项目中预先准备好webp,比如说在UI给切图时,多提供一个webp格式。
目前已有很多loader和plugin来干这个事情,本文中使用的是imagemin-webp-webpack-plugin,配置很简单,样例如下:
import ImageminWebpWebpackPlugin from 'imagemin-webp-webpack-plugin'
...
plugins: [
...
new ImageminWebpWebpackPlugin({
config: [
{
test: /\.(jpe?g|png)/,
options: {
quality: 75
}
}
],
overrideExtension: false
})
]
这边为了后面降级方便,所以overrideExtension设置为false,意思是 image.png
-> image.png.webp
如果这时一切正常的话,你已经获得了一份原始图片和一份webp格式的图片了,如下图:
vue中应用
webp在项目中实际应用,已经有人总结过很多方法了,比如使用<picture>
、nginx拦截等等,既然本文是webp+vue实践,则推荐使用vue-lazyload。
这个组件有很多功能,这里主要讲下如何使用它来快速接入webp。
先引用进来:
import VueLazyload from 'vue-lazyload'
Vue.use(VueLazyload)
直接把src替换成v-lazy
// 原先的写法
<img class="top-image" src="./images/banner.png" />
// vue-lazyload的写法
<img class="top-image" v-lazy="./images/banner-new.png" />
然后,直接npm start或者build,问题来了:./images/banner-new.png
并没有和之前一样,被转成实际的地址。
在vue-loader文档里确认了下:
在模板编译过程中,编译器可以将某些特性转换为 require 调用,例如 src 中的 URL。因此这些目标资源可以被 webpack 处理。例如
<img src="./foo.png">
会找到你文件系统中的./foo.png
并将其作为一个依赖包含在你的包里。
{
video: ['src', 'poster'],
source: 'src',
img: 'src',
image: ['xlink:href', 'href'],
use: ['xlink:href', 'href']
}
在经过一系列骚操作无效后,只能进行曲线救国:
// vue-lazyload的写法
<img v-lazy class="top-image" temp="./images/banner-new.png" />
// 配置vue-loader的transformAssetUrls属性
{
loader: 'vue-loader',
options: {
transformAssetUrls: {
img: ['src', 'temp']
}
}
}
import VueLazyload from 'vue-lazyload'
Vue.use(VueLazyload, {
filter: {
progressive(listener, options) {
// 把temp的值赋给src
listener.src = $(listener.el).attr('temp')
}
}
})
现在,总算可以正常加载图片了,还差最后一步。
import VueLazyload from 'vue-lazyload'
Vue.use(VueLazyload, {
filter: {
progressive(listener, options) {
// 把temp的值赋给src
listener.src = $(listener.el).attr('temp')
},
webp(listener, options) {
// 1. 是否支持webp
// 2. 考虑编译速度及热更新相关问题,DEV环境还是照旧
// 3. 如果是svg的话,照旧
// 4. 做一个防错误处理,是cdn的地址才走webp
if (options.supportWebp && !__DEV__ && !listener.src.endsWith('.svg') && listener.src.startsWith(cdnSetting[__ENV__].publicPath)) {
listener.src += '.webp'
}
}
}
})
webp判断可以根据自己的情况进行调整。
最后,写一个正则全量替换项目中的<img />
。
TODO
- 有一种图片在经过webp处理后,文件体积反而会变得更大,这块如果精益求精的话,最好还是要处理一下,具体参见 为何图片经过OSS缩略之后尺寸变大了?——影响不同格式图片文件大小的一些因素和实际示例。
- css中的background-image等引用的图片也需要兼容webp。
总结
大致就是这样,如有问题,可以回复沟通讨论,谢谢观看。