webp圖片在項目中的實踐

1、什麼是webp

WebP格式,谷歌開發的一種旨在加快圖片加載速度的圖片格式。圖片壓縮體積大約只有JPEG的2/3,並能節省大量的服務器寬帶資源和數據空間。php

2、爲何要用webp

一、減少圖片加載資源的大小、節省用戶流量資源
二、下降服務器流量資源css

壓縮率

圖片壓縮結果,使用webp圖片格式後的圖片資源大幅度減少。html

December活動頁圖片壓縮結果

圖片文件夾大小

3、webp兼容性狀況

webp兼容性

結果:谷歌全面支持、安卓瀏覽器從4.2開始支持。那麼在頁面中對於安卓用戶中圖片資源加載大小會有大幅度降低。前端

4、webp在各大網站的使用

淘寶中大量使用webp。html5

2.png

cdn
各大cdn也是支持webp圖片格式輸出。java

5、項目中的實踐

實踐中對h5活動頁採用webp圖片加載方案。h5 頁面查看地址: http://webp.leewr.comnode

整體實現流程

1544769002(1).png

技術細節

webp兼容性如何檢測?

一、經過js瀏覽器端判斷是否支持webpwebpack

function check_webp_feature(feature, callback) {
    var kTestImages = {
        lossy: "UklGRiIAAABXRUJQVlA4IBYAAAAwAQCdASoBAAEADsD+JaQAA3AAAAAA",
        lossless: "UklGRhoAAABXRUJQVlA4TA0AAAAvAAAAEAcQERGIiP4HAA==",
        alpha: "UklGRkoAAABXRUJQVlA4WAoAAAAQAAAAAAAAAAAAQUxQSAwAAAARBxAR/Q9ERP8DAABWUDggGAAAABQBAJ0BKgEAAQAAAP4AAA3AAP7mtQAAAA==",
        animation: "UklGRlIAAABXRUJQVlA4WAoAAAASAAAAAAAAAAAAQU5JTQYAAAD/////AABBTk1GJgAAAAAAAAAAAAAAAAAAAGQAAABWUDhMDQAAAC8AAAAQBxAREYiI/gcA"
    };
    var img = new Image();
    img.onload = function () {
        var result = (img.width > 0) && (img.height > 0);
        callback(feature, result);
    };
    img.onerror = function () {
        callback(feature, false);
    };
    img.src = "data:image/webp;base64," + kTestImages[feature];
}

二、瀏覽器向服務端發起請求的時候accept 會帶上image/webp 信息,在服務端判斷是否支持webp。nginx

map $http_accept $webp_suffix {
        default   "";
        "~*webp"  ".webp";
}

經過nginx中map方法,查找是否有webp字段,若是有設置$webp_suffix.webp值。經過該值就能夠來判斷是否支持webp。若是支持寫入cookie,前端經過檢測cookie作判斷,是否加載webp圖片。
nginx 中設置cookie代碼git

location / {
  if ($webp_suffix ~* webp) {
    add_header Set-Cookie 'webpAvaile=true; path= /; expires=3153600';
  }
}

在開發中如何使用?

經過設置根節點webpa類來處理css中圖片引入問題。

(function () {
  function addRootTag() {
    var className = document.documentElement.className;
    var name = className ? ' webpa' : 'webpa';
    document.documentElement.className += name ;
  }
  if (/webpAvaile=true/.test(document.cookie)) {
    addRootTag();
    window.webpAvaile = true;
   }
})()
一、css中背景如何引入圖片
lees寫法
.webpbg(@url) {
    background-image: url(@url);
    .webpa & {
        background-image: url('@{url}.webp');
    }
}

在使用的時候採用

.header{
    .webpbg('../image/header.jpg');
}
sass 寫法
@mixin webpbg($url) {
    background-image: url($url);
    @at-root .webpa & {
        background-image: url($url+'.webp');
    }
}

在scss文件中使用

@include webpbg('../image/header.jpg');
二、html中圖片如何引入
html中首圖img中

經過流程能夠知道咱們在頁面上寫入了一個cookie(webpAvaile = true)。在加載頁面的時候咱們在頁面首圖後獲取cookie頁面是否存在webpAvaile,經過變量設置圖片格式。

var headImg = docoment.getElementById('#headImg')
var srcUrl = headImg.getAttribute('data-url')
if ( /webpAvaile=availeable/.test(document.cookies)) {
    // 修改首圖地址
    headImg.setAttribute('src',  srcUrl + '.webp')
} else {
    headImg.setAttribute('src',  srcUrl)
}

這樣咱們就處理了首圖src的圖片格式。可是這樣頁面可能會由於父級元素、圖片都爲設定高度而產生抖動。那麼如何處理?直接設置圖片高度或者父級元素設置最小高度、或固定高度。

html5中有picture標籤能夠選擇加載不一樣圖片,是否能夠利用picture元素去掉js對圖片進行格式的選擇。實踐是可行的。
html5中的picture元素兼容性狀況。
picture兼容性

<picture class="img" >
    <source class="img" srcset="images/banner.jpg.webp" type="image/webp">
    <img class="img" id="headImg" src="images/banner.jpg"/>
</picture>
圖片懶加載

在懶加載的時候,一樣將存儲在data-url中的值修改成是否須要加載webp格式的圖片。

$('[data-url]').each(function(item, index){
    var ext = window.webpAvaile ? '.webp' : ''
    $(this).attr('src', $(this).attr('data-url') + ext)
})
三、頁面模板中使用

頁面模板可能由於後端php、java、node等不一樣的類型,處理方法不同當,但思路仍舊是同樣。經過後端判斷Accept中是否有image/webp,若是有在原圖片格式的後綴後加上.webp。

velocity 模板
![]($!{banner.recordMap.get('圖片地址').value}.750x448.jpg$!{isWebp})

項目上線webp圖片資源如何生成?

方案1、前端打包時node.js生成webp格式圖片
方案2、nginx + lua + imageMagic建立webp圖片

node實現:
gulp 打包時生成webp圖片

經過gulp任務,調用圖片轉化庫生成對應的webp圖片。這樣在打包上傳資源的時候同時把生成的webp圖片資源上傳到服務器。這裏採用了一個webp-batch-convert的庫,其核心是採用cwebp-bin將圖片轉換成webp。

var gulp = require('gulp');
var convert = require('webp-batch-convert');
gulp.task('webp', function () {
    var res = convert.cwebp('./images', './images', {
        q: 80,
        quiet: true
    })
    console.log('total is: ' + res)
})
webpack打包時候利用loaders生成webp圖片資源。

略。

nginx技術實現:

實現過程,對支持webp的請求設置cookies。利用nginx檢測圖片請求是否存在,若是不存在經過lua調用imageMagic建立webp圖片並返回。須要注意的是nginx須要安裝lua支持的模塊。[什麼是lua]()參考這裏。

user  root; # nginx 用戶權限 執行lua建立圖片命令須要讀寫權限
# ...
http {
    include       mime.types;
    server {
        listen       80;
        server_name  webp.leewr.com;
        root         /home/leewr/mono/app/public/december;
        location / {
            if ($webp_suffix ~* webp) {
                add_header Set-Cookie 'webpAvaile=true; path= /;';
            }
        }
        location ~* ^(.+\.(jpg|png|jpeg|gif))(.webp)$ { # 正則匹配圖片 paht/name.jpg.webp 格式的圖片請求
            if (!-f $request_filename) { # 若是圖片不存在
                access_log /usr/local/nginx/logs/december.log main; # 設置日誌文件
                set $request_filepath /home/leewr/mono/app/public/december/$1; # 圖片真實路徑變量
                set $ext $3; # 設置圖片擴展名$ext變量
                content_by_lua_file lua/webp.lua; # 調用nginx/lua目錄下的webp.lua文件
            }
        }
    }
}

下面看lua, lua 中代碼很是簡單。定義command命令,調用系統os.execute(command)執行convert圖片轉換命令。convert是ImageMagic的命令。.. lua 中字符串鏈接。ngx.var.ext是nginx中定義的變量。

local command
command = "convert " ..ngx.var.request_filepath.. " " ..ngx.var.request_filepath..ngx.var.ext
os.execute(command)
ngx.exec(ngx.var.request_uri)

詳細見另外一篇文章,[nginx + lua + ImageMagic實現webp圖片剪切]()。

小結:webp圖片能夠經過webpack、gulp在前端打包的時候生成,也能夠經過nginx層自動完成圖片的轉換。二者均可以達到目的。經過nginx層建立圖片是一個更系統的方案。由於在對圖片進行處理的時,咱們的需求可能不僅是簡單的圖片格式轉換。當咱們須要在不一樣的情形調用不一樣的圖片大小、不一樣圖片格式的圖片的時候,這時候前端就無能爲力了,如須要支持90x90.jpg.webp的圖片。webp格式的支持只是資源管理中一個小需求,爲了知足更多複雜的場景,選擇nginx作圖片轉換會是一個更好的選擇。

最後總結一下:

流程
一、nginx檢測webp支持狀況。
二、添加cookie
三、前端檢測cookie決定是否加載 webp圖片。
開發
一、html根節點添加webpa支持class
二、html中img資源能夠頭圖能夠採用picture方式加載。懶加載圖片手動判斷選擇加載webp圖片格式。
三、css中利用根節點的class編寫樣式。.webpbg('url') 或者 @include webpbg('url')

最後附上項目中全部代碼地址github , h5地址:http://webp.leewr.com

相關文章:
無感知升級支持webp圖片系
nginx + lua + imageMagic實現圖片剪切

相關文章
相關標籤/搜索