天天看點

十:圖檔處理彙總

本節課會講述

webpack4

中的圖檔常用的基礎操作:

  • 圖檔處理 和

    Base64

    編碼
  • 圖檔壓縮
  • 合成雪碧圖

0. 課程源碼和資料

本次課程的代碼目錄(如下圖所示):

>>> 本節課源碼

>>> 所有課程源碼

本節課會講述

webpack4

中的圖檔常用的基礎操作:

  • 圖檔處理 和

    Base64

    編碼
  • 圖檔壓縮
  • 合成雪碧圖

1. 準備工作

如項目代碼目錄展示的那樣,除了常見的

app.js

作為入口檔案,我們将用到的 3 張圖檔放在

/src/assets/img/

目錄下,并在樣式檔案

base.css

中引用這些圖檔。

剩下的内容交給

webpack

打包處理即可。樣式檔案和入口 js 檔案的代碼分别如下所示:

/* base.css */
*,
body {
    margin: 0;
    padding: 0;
}
.box {
    height: 400px;
    width: 400px;
    border: 5px solid #000;
    color: #000;
}
.box div {
    width: 100px;
    height: 100px;
    float: left;
}
.box .ani1 {
    background: url("./../assets/imgs/1.jpg") no-repeat;
}
.box .ani2 {
    background: url("./../assets/imgs/2.jpg") no-repeat;
}
.box .ani3 {
    background: url("./../assets/imgs/3.png") no-repeat;
}           

複制

// app.js
import "style-loader/lib/addStyles";
import "css-loader/lib/css-base";

import "./css/base.css";           

複制

在處理圖檔和進行

base64

編碼的時候,需要使用

url-loader

在壓縮圖檔的時候,要使用

img-loader

插件,并且針對不同的圖檔類型啟用不同的子插件。

postcss-loader

postcss-sprites

則用來合成雪碧圖,減少網絡請求。

是以,在 npm 安裝完相關插件後,

package.json

的内容如下所示:

{
    "devDependencies": {
        "css-loader": "^1.0.0",
        "extract-text-webpack-plugin": "^4.0.0-beta.0",
        "file-loader": "^1.1.11",
        "imagemin": "^5.3.1",
        "imagemin-pngquant": "^5.1.0",
        "img-loader": "^3.0.0",
        "postcss-loader": "^2.1.6",
        "postcss-sprites": "^4.2.1",
        "style-loader": "^0.21.0",
        "url-loader": "^1.0.1",
        "webpack": "^4.16.1"
    }
}           

複制

同時,我們編寫如下

index.html

(假設已經打包好了項目檔案,現在直接引入):

<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <meta http-equiv="X-UA-Compatible" content="ie=edge" />
        <title>Documenttitle>
        <link rel="stylesheet" href="./dist/app.min.css" />
    head>
    <body>
        <div id="app">
            <div class="box">
                <div class="ani1">div>
                <div class="ani2">div>
                <div class="ani3">div>
            div>
        div>
        <script src="./dist/app.bundle.js">script>
    body>
html>           

複制

2. 圖檔處理 和 Base64 編碼

2.1 webpack 配置

為了友善樣式提取,還是利用

extract-text-webpack-plugin

來提取樣式檔案。

同時,在

module.rules

選項中進行配置,以實作讓 loader 識别圖檔字尾名,并且進行指定的處理操作。

代碼如下:

// webpack.config.js

const path = require("path");
const ExtractTextPlugin = require("extract-text-webpack-plugin");

let extractTextPlugin = new ExtractTextPlugin({
    filename: "[name].min.css",
    allChunks: false
});

module.exports = {
    entry: {
        app: "./src/app.js"
    },
    output: {
        publicPath: __dirname + "/dist/",
        path: path.resolve(__dirname, "dist"),
        filename: "[name].bundle.js",
        chunkFilename: "[name].chunk.js"
    },
    module: {
        rules: [
            {
                test: /\.css$/,
                use: ExtractTextPlugin.extract({
                    fallback: {
                        loader: "style-loader"
                    },
                    use: [
                        {
                            loader: "css-loader"
                        }
                    ]
                })
            },
            {
                test: /\.(png|jpg|jpeg|gif)$/,
                use: [
                    {
                        loader: "url-loader",
                        options: {
                            name: "[name]-[hash:5].min.[ext]",
                            limit: 20000, // size <= 20KB
                            publicPath: "static/",
                            outputPath: "static/"
                        }
                    }
                ]
            }
        ]
    },
    plugins: [extractTextPlugin]
};           

複制

通過配置

url-loader

的 limit 選項,可以根據圖檔大小來決定是否進行

base64

編碼。這次配置的是:小于 20kb 的圖檔進行

base64

編碼。

2.2 打包結果

之前提到過,在項目中引入了 3 張圖檔,其中

3.png

是小于 20kb 的圖檔。在指令行中運作

webpack

進行打包,size 小于 20kb 的圖檔被編碼,隻打包了 2 個 size 大于 20kb 的圖檔檔案:

打開浏覽器的控制台,我們的圖檔已經被成功編碼:

3. 圖檔壓縮

3.1 壓縮配置

圖檔壓縮需要使用

img-loader

,除此之外,針對不同的圖檔類型,還要引用不同的插件。比如,我們項目中使用的是 png 圖檔,是以,需要引入

imagemin-pngquant

,并且指定壓縮率。

我們隻需要在上面的配置檔案中将下方代碼:

// ...
{
  test: /\.(png|jpg|jpeg|gif)$/,
  use: [
    {
      loader: "url-loader",
      options: {
        name: "[name]-[hash:5].min.[ext]",
        limit: 20000, // size <= 20KB
        publicPath: "static/",
        outputPath: "static/"
      }
    }
  ]
}
// ...           

複制

替換為下方代碼即可,因為執行順序問題,我們将 url-loader 的 limit 設定成 1kb,來防止壓縮後的 png 圖檔被 base64 編碼:

// ...
{
  test: /\.(png|jpg|jpeg|gif)$/,
  use: [
    {
      loader: "url-loader",
      options: {
        name: "[name]-[hash:5].min.[ext]",
        limit: 1000, // size <= 1KB
        publicPath: "static/",
        outputPath: "static/"
      }
    },
    // img-loader for zip img
    {
      loader: "img-loader",
      options: {
        plugins: [
          require("imagemin-pngquant")({
            quality: "80" // the quality of zip
          })
        ]
      }
    }
  ]
}
// ...           

複制

3.2 打包結果

運作 webpack 打包,檢視打包結果:

是的,如你所見,10.5kb 大小的迅雷圖示,被壓縮到了 1.8kb。圖檔資訊可以去 github 上檢視,在文章開頭有提及 github 位址。

3.3 遺留問題

并沒有解決

jpg

格式圖檔壓縮。根據

img-loader

的官方文檔,安裝了

imagemin-mozjpeg

插件。

但是這個插件的最新版本是

7.0.0

,然而配置後,webpack 啟動會用報錯。

檢視了 github 上的 issue,我将版本回退到

6.0.0

。可以安裝,也可以配置運作,正常打包。但是打包後的 jpg 圖檔大小并沒有變化,也就是說,并沒有被壓縮!!!

希望有大佬可以指點一下小生,萬分感謝

4. 合成雪碧圖

4.1 webpack 配置

在之前的基礎上,配置還是很簡單的,loader 的引入和環境變量都在注釋裡面了:

const path = require("path");
const ExtractTextPlugin = require("extract-text-webpack-plugin");

let extractTextPlugin = new ExtractTextPlugin({
    filename: "[name].min.css",
    allChunks: false
});

/*********** sprites config ***************/
let spritesConfig = {
    spritePath: "./dist/static"
};
/******************************************/

module.exports = {
    entry: {
        app: "./src/app.js"
    },
    output: {
        publicPath: __dirname + "/dist/",
        path: path.resolve(__dirname, "dist"),
        filename: "[name].bundle.js",
        chunkFilename: "[name].chunk.js"
    },
    module: {
        rules: [
            {
                test: /\.css$/,
                use: ExtractTextPlugin.extract({
                    fallback: {
                        loader: "style-loader"
                    },
                    use: [
                        {
                            loader: "css-loader"
                        },
                        /*********** loader for sprites ***************/
                        {
                            loader: "postcss-loader",
                            options: {
                                ident: "postcss",
                                plugins: [
                                    require("postcss-sprites")(spritesConfig)
                                ]
                            }
                        }
                        /*********************************************/
                    ]
                })
            },
            {
                test: /\.(png|jpg|jpeg|gif)$/,
                use: [
                    {
                        loader: "url-loader",
                        options: {
                            name: "[name]-[hash:5].min.[ext]",
                            limit: 10000, // size <= 20KB
                            publicPath: "static/",
                            outputPath: "static/"
                        }
                    },
                    {
                        loader: "img-loader",
                        options: {
                            plugins: [
                                require("imagemin-pngquant")({
                                    quality: "80"
                                })
                            ]
                        }
                    }
                ]
            }
        ]
    },
    plugins: [extractTextPlugin]
};           

複制

4.2 效果展示

按照我們的配置,打包好的雪碧圖被放入了

/dist/static/

目錄下,如下圖所示:

4.3 雪碧圖的實際應用

雪碧圖是為了減少網絡請求,是以被處理雪碧圖的圖檔多為各式各樣的 logo 或者大小相等的小圖檔。而對于大圖檔,還是不推薦使用雪碧圖。

除此之外,雪碧圖要配合 css 代碼進行定制化使用。要通過 css 代碼在雪碧圖上精準定位需要的圖檔(可以了解成從雪碧圖上裁取需要的圖檔),更多可以百度或者 google。