BACK
webp 是 2010年 Google 釋出的圖片格式,針對 PNG 可減少 26%,JPEG 約可減少 25% ~ 34%,目前僅 safari、IE 尚不支援,但 safari 在 ios 14 以後開始支援。 參考網站 Vue CLI 官方webpack相關文檔
前言 webp
是 2010年 Google 釋出的圖片格式,針對 PNG 可減少 26%,JPEG 約可減少 25% ~ 34%,目前僅 safari、IE 尚不支援,但 safari 在 ios 14 以後開始支援。若在未提供 .webp
格式圖檔的情況下,使用套件於 webpack
時進行圖片轉檔,但於 development
下會因抓不到虛擬的 XXX.webp
圖檔而導致 npm run
起時噴錯,可使用以下設定解決此問題。 1
npm i webpack-plugin-image-transform-webp-and-mini
新增一個自訂的 webploader 此 loader
功用為:若 resource 的 query (使用 chainWebpack
提供的變數"resourceQuery
“抓) 字符中含有 "type=webp"
且 resource
為圖片時,將附檔名轉換成 XXX.webp
。 1
2
3
4
5
6
7
8
9
10
11
12
const path = require ( "path" )
module . exports = function ( source , map ) {
let result = source
if ( this . resourceQuery && this . resourceQuery . includes ( "type=webp" ) && ! this . resource . includes ( "data:image" )) {
let extname = path . extname ( this . resourcePath )
result = source . replace ( extname , ".webp" )
}
// return result
this . callback ( null , result , map )
}
chainWebpack
設定套件安裝完成後,vue.config.js
引入套件,並指定webp圖檔存放位置。 引入自訂的 webploader
, 並設定 chainWebpack
的 images
需優先跑 webploader
,再跑 url-loader
與 file-loader
。 主要解決 Vue-cli 的 development
下,會因實際不存在 “XXX.webp” 圖檔而導致開發時報錯的問題。 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
// ...
const ImageminWebpWebpackPlugin = require ( "webpack-plugin-image-transform-webp-and-mini" )
// ...
chainWebpack : config => {
// ...
config . plugins . delete ( "preload-index" )
config . plugins . delete ( "prefetch-index" )
// 相關設定建議放於移除 preload-index 與 prefetch-index 之後
config . plugin ( "webP" ). use ( ImageminWebpWebpackPlugin , [
{
name : "static/img/[name].[hash:8].[ext]" ,
logger : false ,
paths : {
dir : path . resolve ( __dirname , "./src/assets" ),
exclude : []
},
miniOptions : false
}
])
let rule = config . module . rule ( "images" )
rule . uses . clear ()
rule
. use ( "./webploader.js" )
. loader ( "./webploader.js" )
. end ()
. use ( "url-loader" )
. loader ( "url-loader" )
. options ({
limit : 4096 ,
fallback : {
loader : "file-loader" ,
options : {
name : "static/img/[name].[hash:8].[ext]"
}
}
})
// ...
}
補上是否支援 Webp
的判斷,若支援則於 <html>
補上 class name,供CSS抓取 class name 後改讀 webp 圖片 main.js 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
async function isSupportWebp () {
return new Promise ( resolve => {
let result = false
const elem = document . createElement ( "canvas" )
if ( elem . getContext && elem . getContext ( "2d" )) {
result = elem . toDataURL ( "image/webp" ). indexOf ( "data:image/webp" ) === 0
}
resolve ( result )
})
}
// 使用自定义过滤器
filter ( Vue )
;( async () => {
Vue . prototype . $supportWebp = await isSupportWebp ()
if ( Vue . prototype . $supportWebp ) {
document . documentElement . classList . add ( "webp" )
}
})()
若有使用 vue-lazyload
,則補上 vue-lazyload
提供的 webp 相關設定 <img>
使用 v-lazy 時,src的圖片附檔名皆會轉換成 XXX.webp
1
2
3
4
5
6
7
8
9
10
vue . use ( VueLazyload , {
filter : {
webp ( listener ) {
if ( vue . prototype . $supportWebp && !~ listener . src . indexOf ( ".webp" )) {
listener . src = listener . src . replace ( /\.(png|jpe?g)(\?.*)?$/ , ".webp" )
listener . el . setAttribute ( "data-src" , listener . src . replace ( /\.(png|jpe?g)(\?.*)?$/ , ".webp" ))
}
}
}
})
於各個 CSS 中,若 background 使用到需轉 .webp 格式的 img ,補上自行設定的 query ("?type=webp"
),以便 webploader
抓該 query 進行轉換圖檔格式 例如: 1
2
3
4
5
6
7
8
9
10
.page-wrap-main {
background : url("~assets/images/main/bg.png") ;
background-size : cover ;
width : 100 % ;
position : relative ;
.webp & {
background-image : url("~assets/images/main/bg.png?type=webp") ;
}
}
Licensed under CC BY-NC-SA 4.0