本人已經使用vue.js半年多了,在做一些Html5頁面的時候發(fā)現(xiàn)很多頁面都是圖片組成的褐着,如果能有效的壓縮圖片的體積那么整個項目體積就會減少很多,這是為什么寫這個簡單東西的起點托呕。
Webp 百度百科上已經講清楚在保持原畫質的情況呀體積可以壓縮到原來的60%這是很牛逼的一件事含蓉∑盗玻看看webp的兼容情況,下圖是caniuse上面最新的webp支持情況
兼容情況還是不那么樂觀馅扣,不過chrome和安卓陣營已經全部支持斟赚。所以我還是做了這件事。
源碼github
Vue.js
的自定義指令系統(tǒng)十分強大是我做這件事的根本原因之一差油,所以我的設想是在一個指令中傳入圖片鏈接拗军,然后在頁面渲染的時候根據(jù)瀏覽器是否支持webp
格式的圖片選擇下載那個圖片,這里就需要判斷瀏覽器是否支持webp
了,這里我用到的是canvas
方法,代碼如下
var canUseWebp = (function() {
var elem = document.createElement('canvas');
if (!!(elem.getContext && elem.getContext('2d'))) {
return elem.toDataURL('image/webp').indexOf('data:image/webp') === 0;
} else {
return false;
}
})();
這時候就非常簡單了指令在update
的時候根據(jù)是否支持然后選擇不同的圖片
function update(el, option) {
var attr = option.arg || 'src';
if (el.tagName.toLowerCase() === 'img' && option.value) {
el.setAttribute(attr, option.value);
}
};
然而事情的這個時候發(fā)現(xiàn)一些小的圖標不見了拐格,原來我的webpack
配置中設置了小于10k
的圖片使用base64
編碼,
所以最終我的更新代碼是這樣的
function update(el, option) {
var attr = option.arg || 'src';
if (el.tagName.toLowerCase() === 'img' && option.value) {
if (option.value.indexOf('data:image') < 0) {
var tmp = option.value.substring(0, option.value.lastIndexOf('.')) + '.webp';
el.setAttribute(attr, canUseWebp ? tmp : option.value);
} else {
el.setAttribute(attr, option.value);
}
}
};
這個時候vue.js 2.0
發(fā)布了膨蛮。我有針對 2.0版本做了支持,由于我的指令非常簡單,所以代碼很輕松
var isVueNext = Vue.version.split('.')[0] === '2';
if (isVueNext) {
Vue.directive('webp', function(el, binding) {
update(el, {
arg: binding.arg,
value: binding.value
});
})
} else {
Vue.directive('webp', {
bind: function() {},
update: function(val, old) {
update(this.el, {
arg: this.arg,
value: val
});
},
unbind: function() {}
})
}
};
這樣我的vue-webp
指令就算完成了。
只有指令可不行铲汪,每次都要自己生成一份webp
格式的圖片,這太不友好了罐柳。我有查找一番,發(fā)現(xiàn)一個webp-loader
可以在webpack
打包和dev的時候自動生成相應的webp
文件狰住,太好了张吉。使用原作者的webp-loader
發(fā)現(xiàn)文件的hash
不一樣,我又用imagemin
最新版本升級了一下催植,上傳到npm
叫webpn-loader
(原諒我不會命名)肮蛹,
具體使用方法可以參考我的 Vue.js 2.0 后臺項目 模板項目
謝謝大家,看到這里创南。歡迎各種star