| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109 |
- import sharp from 'sharp'
- import { readdir, stat, rename, unlink } from 'fs/promises'
- import { join, extname } from 'path'
- const IMAGE_DIR = 'src/assets/images'
- const IMAGE_EXTENSIONS = ['.png', '.jpg', '.jpeg']
- // 计算文件大小(KB)
- function formatSize(bytes) {
- return (bytes / 1024).toFixed(2) + ' KB'
- }
- // 压缩单个图片
- async function compressImage(fileName) {
- const ext = extname(fileName).toLowerCase()
- const inputPath = join(IMAGE_DIR, fileName)
- const tempPath = join(IMAGE_DIR, 'temp_' + fileName)
- try {
- const inputStats = await stat(inputPath)
- const inputSize = inputStats.size
- let pipeline = sharp(inputPath)
- // 根据图片类型设置压缩参数
- if (ext === '.png') {
- pipeline = pipeline.png({
- compressionLevel: 9,
- palette: true,
- quality: 80
- })
- } else if (ext === '.jpg' || ext === '.jpeg') {
- pipeline = pipeline.jpeg({
- quality: 80,
- mozjpeg: true
- })
- }
- // 执行压缩到临时文件
- await pipeline.toFile(tempPath)
- // 删除原文件并重命名临时文件
- await unlink(inputPath)
- await rename(tempPath, inputPath)
- const outputStats = await stat(inputPath)
- const outputSize = outputStats.size
- const savings = ((inputSize - outputSize) / inputSize * 100).toFixed(1)
- console.log(`✅ ${fileName}`)
- console.log(` 原始:${formatSize(inputSize)} → 压缩后:${formatSize(outputSize)} (节省 ${savings}%)`)
- return { inputSize, outputSize, savings }
- } catch (error) {
- console.error(`❌ 压缩失败 ${fileName}:`, error.message)
- // 清理临时文件(如果存在)
- try {
- await unlink(tempPath)
- } catch (e) {
- // 忽略
- }
- return null
- }
- }
- // 主函数
- async function main() {
- console.log('🚀 开始压缩图片...\n')
- const files = await readdir(IMAGE_DIR)
- const imageFiles = files.filter(file =>
- IMAGE_EXTENSIONS.includes(extname(file).toLowerCase())
- )
-
- if (imageFiles.length === 0) {
- console.log('⚠️ 未找到需要压缩的图片')
- return
- }
- console.log(`📁 找到 ${imageFiles.length} 张图片\n`)
- let totalInput = 0
- let totalOutput = 0
- let successCount = 0
- for (const file of imageFiles) {
- const result = await compressImage(file)
- if (result) {
- totalInput += result.inputSize
- totalOutput += result.outputSize
- successCount++
- console.log()
- }
- }
- const totalSavings = ((totalInput - totalOutput) / totalInput * 100).toFixed(1)
- console.log('='.repeat(50))
- console.log(`📊 压缩完成!`)
- console.log(` 成功:${successCount}/${imageFiles.length} 张`)
- console.log(` 原始总大小:${formatSize(totalInput)}`)
- console.log(` 压缩后总大小:${formatSize(totalOutput)}`)
- console.log(` 总计节省:${totalSavings}% (${formatSize(totalInput - totalOutput)})`)
- console.log('='.repeat(50))
- }
- // 运行
- main().catch(console.error)
|