# 使用 Node.js 实现 PNG/JPG 到 WebP 的批量转换工具
在现代 Web 开发中,图片优化是提升用户体验的重要手段。WebP 格式凭借更高的压缩率和优秀的画质成为图片优化的热门选择。本文将指导你如何用 Node.js 开发一个工具,将指定目录及其子目录下的 PNG 和 JPG 图片批量转换为 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
开始任务,完成后打印日志。
运行方法
-
安装依赖
在项目根目录下运行以下命令安装所需依赖:npm install webp-converter
-
目录结构
确保项目目录中存在以下结构:├── script.js # 工具脚本 ├── assets/ # 存放图片的目录 │ ├── image1.png │ ├── image2.jpg │ └── subdir/ │ └── image3.png
-
运行工具
使用 Node.js 运行脚本:node script.js
-
查看结果
转换后的.webp
文件将存放在原图片所在的目录中。
优化点说明
1. 异步操作
- 使用
fs.promises
替代同步 API。 - 通过
async/await
实现非阻塞操作,提高任务效率。
2. 错误处理
- 在文件操作和转换过程中加入
try-catch
,避免单个错误中断整个任务。
3. 日志输出
- 在每个关键步骤打印日志信息,帮助用户了解任务状态。
4. 减少冗余
- 避免重复路径计算和状态检查,提升代码清晰度。
可扩展功能
-
支持 CLI 参数
修改代码以支持通过命令行传递目标路径和转换参数:node script.js --dir ../assets --quality 90
-
并发优化
对大量图片的转换任务,使用并发控制库(如p-limit
)限制同时进行的转换任务数量。 -
图片压缩优化
在生成 WebP 文件前,先对原始图片进行压缩,进一步降低文件大小。
总结
通过本工具,我们可以轻松实现 PNG/JPG 图片的批量转换,从而显著优化网站图片资源的加载性能。无论是简单的个人项目,还是复杂的生产环境,这个工具都可以为你的开发流程增添效率。如果你在项目中需要优化图片资源,不妨尝试一下这个工具!