使用 Node.js 实现 PNG JPG 到 WebP 的批量转换工具

# 使用 Node.js 实现 PNG/JPG 到 WebP 的批量转换工具

在现代 Web 开发中,图片优化是提升用户体验的重要手段。WebP 格式凭借更高的压缩率和优秀的画质成为图片优化的热门选择。本文将指导你如何用 Node.js 开发一个工具,将指定目录及其子目录下的 PNGJPG 图片批量转换为 WebP 格式。

---

## 目标功能

我们希望工具能够实现以下目标:
1. 扫描指定目录,包括所有子目录。
2. 检测 `.png``.jpg` 文件并将其转换为 `.webp` 格式。
3. 如果目标文件已经存在,跳过转换。
4. 提供清晰的日志输出,便于监控任务执行状态。
5. 添加错误处理机制,确保工具运行稳定。

---

## 技术实现

工具的开发将使用以下技术和工具:
- **Node.js**:提供文件操作和异步处理能力。
- **`webp-converter`**:一个封装 WebP 转换工具的库。
- **文件系统模块(`fs``path`**:读取文件、目录及路径处理。
- **异步编程(`async/await`**:提高效率,避免阻塞。

---

## 完整代码

以下是实现工具的完整代码:


const fs = require('fs').promises;
const path = require('path');
const webp = require('webp-converter');

// 授予 webp-converter 权限
webp.grant_permission();

async function generateWebp(dir, file) {
  const filePrefix = file.substring(0, file.lastIndexOf('.'));
  const sourceFile = path.join(dir, file);
  const webpFile = path.join(dir, `${filePrefix}.webp`);

  try {
    // 检查目标 WebP 文件是否已存在
    const webpExists = await fs.stat(webpFile).then(() => true).catch(() => false);
    if (webpExists) {
      console.log(`WebP file already exists: ${webpFile}`);
      return;
    }

    // 调用 webp 转换工具
    const result = await webp.cwebp(sourceFile, webpFile, '-q 80'); // 设置质量为 80
    console.log(`Converted: ${sourceFile} -> ${webpFile}`);
    console.log(result);
  } catch (error) {
    console.error(`Error converting file ${sourceFile}:`, error.message);
  }
}

async function scanDirectory(directoryPath) {
  try {
    // 读取目录内容
    const files = await fs.readdir(directoryPath, { withFileTypes: true });

    // 遍历文件和子目录
    for (const file of files) {
      const filePath = path.join(directoryPath, file.name);

      if (file.isFile()) {
        // 检查文件类型是否为 PNG 或 JPG
        if (file.name.endsWith('.png') || file.name.endsWith('.jpg')) {
          await generateWebp(directoryPath, file.name);
        }
      } else if (file.isDirectory()) {
        // 递归处理子目录
        await scanDirectory(filePath);
      }
    }
  } catch (error) {
    console.error(`Error scanning directory ${directoryPath}:`, error.message);
  }
}

// 主函数
(async function main() {
  const directoryPath = path.resolve(__dirname, '../assets');
  console.log(`Starting scan in directory: ${directoryPath}`);
  await scanDirectory(directoryPath);
  console.log('Scan completed.');
})();

代码结构详解

1. 文件转换函数 generateWebp

该函数负责将单个图片文件转换为 WebP 格式:

  • 检查目标 WebP 文件是否已存在,避免重复操作。
  • 使用 webp.cwebp 进行格式转换,设置质量参数为 80
  • 捕获并打印错误信息,确保工具不会因为单个文件出错而中断。

2. 扫描目录函数 scanDirectory

递归扫描指定目录及其子目录:

  • 使用 fs.readdir 获取目录内容并区分文件和子目录。
  • 对符合条件的文件调用 generateWebp 转换。
  • 遇到子目录时递归调用 scanDirectory

3. 主函数 main

初始化扫描路径并调用 scanDirectory 开始任务,完成后打印日志。


运行方法

  1. 安装依赖
    在项目根目录下运行以下命令安装所需依赖:

    npm install webp-converter
    
  2. 目录结构
    确保项目目录中存在以下结构:

    ├── script.js   # 工具脚本
    ├── assets/     # 存放图片的目录
    │   ├── image1.png
    │   ├── image2.jpg
    │   └── subdir/
    │       └── image3.png
    
  3. 运行工具
    使用 Node.js 运行脚本:

    node script.js
    
  4. 查看结果
    转换后的 .webp 文件将存放在原图片所在的目录中。


优化点说明

1. 异步操作

  • 使用 fs.promises 替代同步 API。
  • 通过 async/await 实现非阻塞操作,提高任务效率。

2. 错误处理

  • 在文件操作和转换过程中加入 try-catch,避免单个错误中断整个任务。

3. 日志输出

  • 在每个关键步骤打印日志信息,帮助用户了解任务状态。

4. 减少冗余

  • 避免重复路径计算和状态检查,提升代码清晰度。

可扩展功能

  1. 支持 CLI 参数
    修改代码以支持通过命令行传递目标路径和转换参数:

    node script.js --dir ../assets --quality 90
    
  2. 并发优化
    对大量图片的转换任务,使用并发控制库(如 p-limit)限制同时进行的转换任务数量。

  3. 图片压缩优化
    在生成 WebP 文件前,先对原始图片进行压缩,进一步降低文件大小。


总结

通过本工具,我们可以轻松实现 PNG/JPG 图片的批量转换,从而显著优化网站图片资源的加载性能。无论是简单的个人项目,还是复杂的生产环境,这个工具都可以为你的开发流程增添效率。如果你在项目中需要优化图片资源,不妨尝试一下这个工具!


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值