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(/[\n\t]/);
    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

posted @ 2020-04-06 17:39  dora_zc  阅读(934)  评论(0编辑  收藏  举报