为什么要压缩图片
图片是网站很重要的构成部分,可以通过脚本实现自动化压缩图片。还能凑一波绩效,简直美滋滋。
图片的加载速度对用户体验有很大的影响,而压缩图片体积是提升加载速度最有效的方法。今天为大家推荐一个无损的压缩工具:tinify(大熊猫)。
tinify使用
把图拖进去,然后下载压缩后的图片就可以。 存在的问题:
- 很多人没有开发前压缩的习惯。
- 项目已经积累的图片怎么办。(我在做的时候,项目已经积累了上千张图片)
自动化压缩(tinify继承进项目中)
目标:在根目录执行npm run tinify,就可以压缩项目中的图片。
1、安装tinify、md5
npm i tinify md5
复制代码
2、准备阶段
- 新建tinify.js文件
- 引入tinify进行压缩、fs读取文件、glob获取所有图片路径;
- KEYS可以从官网申请,详情在文末详解;
- 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的额度
- 注入key(每个key的额度是500);
- 获取当前key还有多少额度compressionCount;
- compressionCount大于400时,keyIndex++使用下一个key,keyIndex > KEYS.length后,报错“Tinify额度不足,请添加KEY!”;
- 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、读取所有图片
- glob.sync读取目录下所有的图片
- list.filter过滤掉一些图片,太小的不需要压缩
- 根据路径读取文件执行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、执行压缩
- tinify.fromBuffer(buf)执行压缩
- toBuffer返回压缩后的文件流
- 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做优化
- 引入md5
- 新建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使用规则
使用邮箱申请账号
- 每个账号每月500张额度
- 每个账号可以申请多个key,每个key使用500次之后也作废。
- 多个key使用加起来,每月不能超过500
获取key
在点我进入 页面中搜索dashboard,点击进入管理后台。就可以申请key了。