Loading

git 提交 实现大图自动压缩功能

场景

在一般的网页开发过程中,往往我们都要下载较多的切图,而这些切图未必都做了压缩,即使做了压缩,效果未必能达到理想效果。

要解决这种图片压缩问题,途径有很多

1. 手动将图片丢到xx站点,压缩好之后再放进项目

2. 让UI给已经压缩好的图

这些方式都得靠人工操作,人工操作往往存在一些不确定性,比如忘记了要压缩,也察觉不出来,如果是多人开发,问题会更大。下面我将列举一些常规的解决方案

1. 当代码提交时,拦截大图的提交,提醒开发人员手动压缩(之前博文有实现过)

2. 当提交代码时,主动压缩大图并自动提交(本期讨论重点)

本期将解决方案2展开讨论:主动压缩大图并自动提交

1.安装 Husky:

确保你已经在项目中安装了 Husky。如果还没有安装,可以使用以下命令:

npm install husky --save-dev

2.启用 Git 钩子:

运行以下命令以启用 Husky 钩子:

npx husky install

3.添加 pre-commit 钩子:

使用 Husky 添加 pre-commit 钩子:

npx husky add .husky/pre-commit "npx lint-staged"

4.安装 lint-staged:

为了配合 Husky,安装 lint-staged 来处理文件:

npm install lint-staged --save-dev

5.配置 lint-staged:

package.json 中添加 lint-staged 配置:

{
  "lint-staged": {
    "**/*.{weapp,jpg,png}": "node scripts/compress-images.mjs"
  }
}

6.编写图片压缩脚本(tinify):

安装相关依赖

pnpm install tinify fs-extra glob --save-dev

在项目中创建一个 scripts 文件夹,并在其中添加 compress-images.mjs 文件,内容如下:

程序所包含的逻辑

1. 压缩使用的是tinify压缩工具,官网 https://tinypng.com/

2. 它只压缩图片大于300kb的图

3. 压缩的图将覆盖原图

4. 只有在 git commit -m 'xx' 时会触发图片压缩

import tinify from 'tinify';
import fs from 'fs-extra';

// 设置你的 Tinify API key
tinify.key = 'xxx';

const SIZE_LIMIT = 300 * 1024; // 300KB

async function compressImage(filePath) {
  try {
    const stats = await fs.stat(filePath);

    // 检查文件大小和压缩标记
    if (stats.size < SIZE_LIMIT) {
      console.log(`跳过 ${filePath} (小于300KB)`);
      return;
    }
    console.log(`压缩中: ${filePath}`);

    // 使用 tinify 压缩图片
    const source = tinify.fromFile(filePath);
    await source.toFile(filePath);


    console.log(`压缩完成: ${filePath}`);
  } catch (error) {
    console.error(`压缩失败 ${filePath}:`, error);
  }
}

async function main() {
  try {
    // 获取待提交的文件列表
    const files = process.argv.slice(2);
    console.log(`找到 ${files.length} 个图片文件`);

    // 并发压缩图片
    await Promise.all(files.map(compressImage));

    console.log('所有图片压缩完成!');
  } catch (error) {
    console.error('发生错误:', error);
    process.exit(1);
  }
}

main();

其他场景

有时候你可能需要再已提交的图片中压缩图片,只需要运行一行命令就能处理整个项目的图片压缩

在package.josn 中 的scripts添加命令

"scripts": {
  "compress": "node scripts/compress-images.mjs"
}

在scripts中创建compress-images.mjs,内容如下

程序所包含的逻辑

1. 压缩使用的是tinify压缩工具,官网 https://tinypng.com/

2. 它只压缩图片大于300kb的图

3. 图片压缩完之后会在图片同级目录生成一个文件已压缩标识 例如:我对a.png图片进行了压缩,那同级目录就会生成a.compress-marker 空白文件,只有每次压缩前都会判断这个文件有没有被压缩

4. 压缩的图将覆盖原图

import tinify from 'tinify';
import fs from 'fs-extra';
import {glob} from 'glob';

// 设置你的 Tinify API key
tinify.key = 'xxx';

// 压缩标记文件
const COMPRESS_MARKER = '.compress-marker';
const SIZE_LIMIT = 300 * 1024; // 300KB

async function compressImage(filePath) {
  try {
    const stats = await fs.stat(filePath);
    const markerPath = `${filePath}${COMPRESS_MARKER}`;

    // 检查文件大小和压缩标记
    if (stats.size < SIZE_LIMIT || await fs.pathExists(markerPath)) {
      console.log(`跳过 ${filePath} (已压缩或小于300KB)`);
      return;
    }

    console.log(`压缩中: ${filePath}`);

    // 使用 tinify 压缩图片
    const source = tinify.fromFile(filePath);
    await source.toFile(filePath);

    // 添加压缩标记
    await fs.writeFile(markerPath, '');

    console.log(`压缩完成: ${filePath}`);
  } catch (error) {
    console.error(`压缩失败 ${filePath}:`, error);
  }
}

async function main() {
  try {
    // 获取所有图片文件
    // const files = glob.sync('**/*.{png,jpg,jpeg}', {
    //   ignore: ['node_modules/**', 'dist/**']
    // });

    // 获取待提交的文件列表
    const files = process.argv.slice(2);

    console.log(`找到 ${files.length} 个图片文件`);

    // 并发压缩图片
    await Promise.all(files.map(compressImage));

    console.log('所有图片压缩完成!');
  } catch (error) {
    console.error('发生错误:', error);
    process.exit(1);
  }
}

main();

 

posted @ 2024-12-11 17:28  冯叶青  阅读(10)  评论(0编辑  收藏  举报