让网站飞起来—图片压缩

为什么要压缩图片

图片是网站很重要的构成部分,可以通过脚本实现自动化压缩图片。还能凑一波绩效,简直美滋滋。

图片的加载速度对用户体验有很大的影响,而压缩图片体积是提升加载速度最有效的方法。今天为大家推荐一个无损的压缩工具:tinify(大熊猫)。

tinify使用

把图拖进去,然后下载压缩后的图片就可以。 WechatIMG66.png 存在的问题:

  1. 很多人没有开发前压缩的习惯。
  2. 项目已经积累的图片怎么办。(我在做的时候,项目已经积累了上千张图片)

自动化压缩(tinify继承进项目中)

目标:在根目录执行npm run tinify,就可以压缩项目中的图片

1、安装tinify、md5

npm i tinify md5
复制代码

2、准备阶段

  1. 新建tinify.js文件
  2. 引入tinify进行压缩、fs读取文件、glob获取所有图片路径;
  3. KEYS可以从官网申请,详情在文末详解;
  4. keyIndex确定使用第几个key、total记录要压缩的文件总数、handleCount记录当前压缩的多少文件;
const tinify = require('tinify');
const fs = require('fs');
const glob = require('glob');

const KEYS = [
  "4HMC1HrQjWcvg1TTd5q7l47BhZmc8GBV",
  "R4QKQm0mnBSyb28jpRpzTtRrbGMxMGQZ",
  "z4ZPxWYGX6t5cxfR2g7T7j9JZ1M5l5V1",
];

let keyIndex = 0;
let total = 0;
let handleCount = 0; // 已处理文件数
复制代码

3、判断key的额度

  1. 注入key(每个key的额度是500);
  2. 获取当前key还有多少额度compressionCount;
  3. compressionCount大于400时,keyIndex++使用下一个key,keyIndex > KEYS.length后,报错“Tinify额度不足,请添加KEY!”;
  4. compressionCount小于400时,执行checkFile;
// 开始任务
const startTask = () => {
  const key = KEYS[keyIndex];
  tinify.key = key;
  tinify.validate(err => {
    const { compressionCount = 500 } = tinify;

    // 最大额度500,处理前预留100额度
    if (compressionCount < 400) {
      checkFile();
    } else {
      keyIndex++;
      if (keyIndex < KEYS.length) {
        startTask();
      } else {
        throw new Error('Tinify额度不足,请添加KEY!');
      }
    }
  });
};
复制代码

4、读取所有图片

  1. glob.sync读取目录下所有的图片
  2. list.filter过滤掉一些图片,太小的不需要压缩
  3. 根据路径读取文件执行doTinify压缩
const checkFile = () => {
  let list = glob.sync('./src/**/*.@(png|jpg|jpeg)');
  // 4k以上的文件不压缩
  list = list.filter((i) => fs.statSync(i)?.size > 10000)
  // 待处理文件数
  total = list.length;
  list.forEach(path => {
    const key = path.replace('./src/', '');
    fs.readFile(path, (err, buf) => {
        doTinify(key, path, buf);
    });
  });
};
复制代码

5、执行压缩

  1. tinify.fromBuffer(buf)执行压缩
  2. toBuffer返回压缩后的文件流
  3. fs.writeFile把文件流覆盖原文件
const doTinify = (key, path, buf) => {
  tinify.fromBuffer(buf).toBuffer((err, result) => {
    handleCount++;
    // 覆盖源文件
    fs.writeFile(path, result);
  });
};
复制代码

6、在package.json中添加脚本

路径不要写错,就可以压缩代码了。但我们还要做优化。

 "tinify": "node ./scripts/tinify.ts"
复制代码

7、使用md5做优化

  1. 引入md5
  2. 新建tinifymd5.json文件,把压缩过的文件根据目录做标记,避免重复压缩

具体使用可以看全部代码:

全部代码

const tinify = require('tinify');
const fs = require('fs');
const glob = require('glob');
const md5 = require('md5');
const configPath = './scripts/tinifymd5.json';

// 读取已压缩文件md5
const tinifyMd5 = JSON.parse(fs.readFileSync(configPath).toString());

const KEYS = [
  "4HMB1HrQjWcvg1TTd5q7l47BhZmc8GBV",
  "R4QGQm0mnBSyb28jpRpzTtRrbGMxMGQZ",
  "z4ZRxWYGX6t5cxfR2g7T7j9JZ1M5l5V1",
];

let keyIndex = 0;
let total = 0;
let handleCount = 0; // 已处理文件数

// 开始任务
const startTask = () => {
  const key = KEYS[keyIndex];
  tinify.key = key;
  tinify.validate(err => {
    const { compressionCount = 500 } = tinify;

    if (err) {
      console.log(`[error] ${key}`, String(err));
    } else {
      console.log(`[compressionCount] ${key}`, compressionCount);
    }

    // 最大额度500,处理前预留100额度
    if (compressionCount < 400) {
      checkFile();
    } else {
      keyIndex++;
      if (keyIndex < KEYS.length) {
        startTask();
      } else {
        console.log("遇到报错看文档:http://wiki.duxiaoman-int.com/pages/viewpage.action?pageId=168130093")
        throw new Error('Tinify额度不足,请添加KEY!');
      }
    }
  });
};

// 检查是否需要压缩
const checkFile = () => {
  let list = glob.sync('./src/**/*.@(png|jpg|jpeg)');
  // 4k以上的文件不压缩
  list = list.filter((i) => fs.statSync(i)?.size > 10000)
  // 待处理文件数
  total = list.length;
  list.forEach(path => {
    const key = path.replace('./src/', '');
    fs.readFile(path, (err, buf) => {
      if (tinifyMd5[key] !== md5(buf) && !err) {
        doTinify(key, path, buf);
      } else {
        console.log(`${err ? 'Error' : 'Ignore'}: ${key} ${err || ''}`);
        handleCount++;
        updateTinifyMd5()
      }
    });
  });
};

const doTinify = (key, path, buf) => {
  tinify.fromBuffer(buf).toBuffer((err, result) => {
    handleCount++;
    if (err) {
      console.log(`Error: ${err} ${key}`);
      updateTinifyMd5()
    } else {
      // 覆盖源文件
      fs.writeFile(path, result, () => {
        // 更新md5
        tinifyMd5[key] = md5(result);
        console.log('Tinified: ' + key);

        updateTinifyMd5()
      });
    }
  });
};
function updateTinifyMd5() {
  if (handleCount === total) {
    console.log("遇到报错看文档:http://wiki.duxiaoman-int.com/pages/viewpage.action?pageId=168130093")
    fs.writeFileSync(configPath, JSON.stringify(tinifyMd5, null, 2));
  }
}

startTask();
复制代码

key使用规则

使用邮箱申请账号

  1. 每个账号每月500张额度
  2. 每个账号可以申请多个key,每个key使用500次之后也作废。
  3. 多个key使用加起来,每月不能超过500

获取key

点我进入 页面中搜索dashboard,点击进入管理后台。就可以申请key了。

猜你喜欢

转载自juejin.im/post/7049168908049186852