# Tinypng CLI：高效的图片压缩工具

Tinypng CLI 是一个基于 **[Tinypng.com](https://tinypng.com/)** 网页版实现的命令行工具，支持多种格式转换和压缩包操作。
<img src="https://img.shields.io/npm/v/@julytian/tinypng-cli?style=flat-square" alt="npm version" />

## 特性

- 支持多种图片格式： png、jpg、jpeg、webp
- 便捷的压缩方式： 单张图片、整个文件夹或压缩包
- 灵活的图片格式转换： png、jpg、jpeg、webp 之间的互转
- 压缩包解压缩： 支持 tar、zip、tgz 格式
- 压缩后的图片打包： 生成 tar、zip、tgz 等格式的压缩包

## 环境要求

- **Node.js ≥ 24**（v3.x 全面 ESM 化，依赖原生 `fetch`、`node:util.parseArgs`、`fs.glob`、import attributes）

> 仍需在旧版本 Node 上使用？请继续使用 v2.x：`npm i @julytian/tinypng-cli@2`。

### 安装

```shell
# npm
npm i @julytian/tinypng-cli -g

# yarn
yarn i @julytian/tinypng-cli -g

# pnpm
pnpm i @julytian/tinypng-cli -g
```

## 快速上手

```shell
$ tinypng <file> [options]
# 帮助信息
$ tinypng --help
# 版本信息
$ tinypng --version
# 多语言设置输出 (zh, en)
$ tinypng -l zh
# 压缩单张图片
$ tinypng a.png
# 压缩单张图片并将 png 格式图片转换为 jpeg 格式
$ tinypng a.png -c jpeg
# 压缩单张图片并生成 zip 格式包
$ tinypng a.png -z
# 压缩单张图片并生成 tar 格式包
$ tinypng a.png -z tar
# 压缩 a 目录下的图片
$ tinypng a
# 递归遍历 a 目录,压缩 a 目录下的所有的图片
$ tinypng a -r
# 压缩目录下的图片并生成 zip 格式包
$ tinypng a -z
# 压缩目录下的所有图片并生成 zip 格式包
$ tinypng a -r -z
# 压缩目录下的所有图片并生成 tgz 格式包
$ tinypng a -r -z tgz
# 解压 zip 格式包并压缩里面的图片
$ tinypng a.zip
# 解压 zip 格式包并压缩里面的图片,并重新生成 zip 格式包
$ tinypng a.zip -z
# 解压 zip 格式包并压缩里面的图片,并重新生成 tar 格式包
$ tinypng a.zip -z tar
```

## 选项

- -h, --help: 显示帮助信息。
- -v, --version: 显示版本号。
- -z, --zip <格式>: 生成指定格式的压缩包 (zip, tar, tgz)。
- -c, --convert <格式>: 将图片转换为指定格式 (png, jpg, jpeg, webp)。
- -r, --recursive: 递归遍历文件夹。
- -l, --language <语言>: 设置输出语言 (zh, en)。

## 案例

```shell
# 压缩名为 "a.png" 的图片
$ tinypng a.png

# 压缩名为 "a.png" 的图片并转换为 jpeg 格式
$ tinypng a.png -c jpeg

# 压缩名为 "a.png" 的图片并生成 zip 包
$ tinypng a.png -z

# 压缩名为 "images" 的文件夹下的所有图片
$ tinypng images -r

# 解压名为 "images.zip" 的 zip 包并压缩里面的所有图片
$ tinypng images.zip
```

## v3 亮点

Tinypng CLI v3 是一次完整的内部重写，对外 CLI 用法 100% 兼容，内部全面现代化：

- **ESM-only 单文件 bundle**（`dist/index.mjs`，压缩后约 10 KB），由 [tsdown](https://github.com/sxzz/tsdown) 构建。
- **函数式 pipeline** —— 5 个 stage（`resolveInputs → uploadImages → downloadResults → renderReport → maybeArchive`）取代旧的 god class。
- **并发上传**：`p-limit` 控制（默认 6，受 TinyPNG 后端容量约束）。
- **拥抱原生 Node API**：用 `node:util.parseArgs`、`fs.glob`、原生 `fetch`、import attributes 替换 `minimist`、`fs-extra`、`fast-glob`、`mime-types`、`nanospinner` 等。runtime 依赖 16 → 8。
- **i18n 内联**：翻译资源在构建期内联，启动时不再读文件。
- **82 个单测 + e2e**（`node:test` + `undici.MockAgent`），TypeScript 6 严格模式（`exactOptionalPropertyTypes`、`noUncheckedIndexedAccess`）。
- **更明确的退出码**：`0`（成功）、`1`（全部失败）、`2`（打包失败）、`64`（参数非法）、`74`（IO 错误）、`70`（未知错误）。

完整迁移说明见 [CHANGELOG.md](./CHANGELOG.md)。

## 许可证

本项目采用 [MIT 许可证](https://github.com/julytian/tinypng-cli/blob/main/LICENSE)。
