pre-commit + imagemin 實現圖片自動壓縮

我們日常開發的前端項目中,圖片資源會佔到項目資源的很大比例,因此在考慮到性能優化,頁面載入速度的時候,如何更好地處理圖片就非常重要了。

首先我們可以想到的方案是:使用webpackimage-webpack-loader來壓縮圖片。但是這種方案有個弊端,就是webpack每次構建的時候都要處理一次圖片壓縮,會影響到webpack的構建速度。

接下來要講的是 pre-commit + imagemin 實現的圖片自動壓縮方案,思路是在我們git commit 時,將要提交的圖片文件替換為壓縮後的文件。

安裝依賴

npm install pre-commit imagemin imagemin-pngquant -D  

修改 package.json

// package.json  {    ....      "scripts": {      "imagemin": "node imagemin.js"    },    "pre-commit": [      "imagemin"    ],  }  

在項目根目錄下新建 imagemin.js

const execSync = require("child_process").execSync;  const path = require("path");  const imagemin = require("imagemin");  const imageminPngquant = require("imagemin-pngquant");  console.log("pre-commit hook start imagemin! n");  let diff = getDiffFiles();  compressPics(diff);    function getDiffFiles(type) {    // pre-commit鉤子本身不傳遞參數    //https://git-scm.com/docs/githooks/1.7.4#_pre_commit    // 所以通過git diff 命令拿到本次提交涉及的變動文件    let root = process.cwd();    let files = execSync("git diff --cached --name-status HEAD")      .toString()      .split("n");    let result = [];    // add, delete, modified, renamed, copied    type = type || "admrc";    let types = type.split("").map(t => {      return t.toLowerCase();    });    files.forEach(file => {      if (!file) {        return;      }      let temp = file.split(/[nt]/);      let status = temp[0].toLowerCase();      let filePath = root + "/" + temp[1];      let extName = path.extname(filePath).slice(1);        if (types.length && ~types.indexOf(status)) {        result.push({          status: status, // admrc中的一個          path: filePath, // 絕對路徑          subpath: temp[1], // 相對路徑          extName: extName // 擴展名        });      }    });    return result;  }    function compressPics(files) {    let pngs = files.filter(      file => file.extName === "png" && ["a", "m"].includes(file.status)    );    console.log(pngs);    let parentFolder = {};    pngs.forEach(x => {      // 根據不同父級目錄分類      let pf = x.subpath.slice(0, x.subpath.lastIndexOf("/"));      parentFolder[pf]        ? parentFolder[pf].push(x.subpath)        : (parentFolder[pf] = [x.subpath]);    });      for (let pf in parentFolder) {      imagemin(parentFolder[pf], {        // 原圖片目錄        destination: pf, // 生成圖片的目錄        plugins: [          imageminPngquant({            speed: 1,            quality: [0.4, 0.5]          })        ]      })        .then(res => {          console.log(res);          execSync("git add . ");        })        .catch(err => {          console.log(err);          process.exit(1);        });    }  }    

提交圖片

執行 git commit 命令後,如果檢測到有 png 格式的圖片,會進行壓縮處理後再提交。

我們把已經提交過的 pic.png 重命名為 pic1.png,不會再次進行壓縮。

圖片壓縮後的效果

原來的圖片大小 3.2M

壓縮後 695.28kb