Files
vf_react/optimize-images.js
2025-10-13 19:53:13 +08:00

130 lines
3.5 KiB
JavaScript
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 图片优化脚本 - 使用sharp压缩PNG图片
const sharp = require('sharp');
const fs = require('fs');
const path = require('path');
// 需要优化的大图片列表 (> 500KB)
const LARGE_IMAGES = [
'CoverImage.png',
'BasicImage.png',
'teams-image.png',
'hand-background.png',
'basic-auth.png',
'BgMusicCard.png',
'Landing2.png',
'Landing3.png',
'Landing1.png',
'smart-home.png',
'automotive-background-card.png'
];
const IMG_DIR = path.join(__dirname, 'src/assets/img');
const BACKUP_DIR = path.join(IMG_DIR, 'original-backup');
// 确保备份目录存在
if (!fs.existsSync(BACKUP_DIR)) {
fs.mkdirSync(BACKUP_DIR, { recursive: true });
}
console.log('🎨 开始优化图片...');
console.log('================================\n');
let totalBefore = 0;
let totalAfter = 0;
let optimizedCount = 0;
async function optimizeImage(filename) {
const srcPath = path.join(IMG_DIR, filename);
const backupPath = path.join(BACKUP_DIR, filename);
if (!fs.existsSync(srcPath)) {
console.log(`⚠️ 跳过: ${filename} (文件不存在)`);
return;
}
try {
// 获取原始大小
const beforeStats = fs.statSync(srcPath);
const beforeSize = beforeStats.size;
totalBefore += beforeSize;
// 备份原始文件
if (!fs.existsSync(backupPath)) {
fs.copyFileSync(srcPath, backupPath);
}
// 读取图片元数据
const metadata = await sharp(srcPath).metadata();
// 优化策略:
// 1. 如果宽度 > 2000px缩放到 2000px
// 2. 压缩质量到 85
// 3. 使用 pngquant 算法压缩
let pipeline = sharp(srcPath);
if (metadata.width > 2000) {
pipeline = pipeline.resize(2000, null, {
withoutEnlargement: true,
fit: 'inside'
});
}
// PNG优化
pipeline = pipeline.png({
quality: 85,
compressionLevel: 9,
adaptiveFiltering: true,
force: true
});
// 保存优化后的图片
await pipeline.toFile(srcPath + '.tmp');
// 替换原文件
fs.renameSync(srcPath + '.tmp', srcPath);
// 获取优化后的大小
const afterStats = fs.statSync(srcPath);
const afterSize = afterStats.size;
totalAfter += afterSize;
// 计算节省的大小
const saved = beforeSize - afterSize;
const percent = Math.round((saved / beforeSize) * 100);
if (saved > 0) {
optimizedCount++;
console.log(`${filename}`);
console.log(` ${Math.round(beforeSize/1024)} KB → ${Math.round(afterSize/1024)} KB`);
console.log(` 节省: ${Math.round(saved/1024)} KB (-${percent}%)\n`);
} else {
console.log(` ${filename} - 已经是最优化状态\n`);
}
} catch (error) {
console.error(`${filename} 优化失败:`, error.message);
}
}
async function main() {
// 依次优化每个图片
for (const img of LARGE_IMAGES) {
await optimizeImage(img);
}
console.log('================================');
console.log('📊 优化总结:\n');
console.log(` 优化前总大小: ${Math.round(totalBefore/1024/1024)} MB`);
console.log(` 优化后总大小: ${Math.round(totalAfter/1024/1024)} MB`);
const totalSaved = totalBefore - totalAfter;
const totalPercent = Math.round((totalSaved / totalBefore) * 100);
console.log(` 节省空间: ${Math.round(totalSaved/1024/1024)} MB (-${totalPercent}%)`);
console.log(` 成功优化: ${optimizedCount}/${LARGE_IMAGES.length} 个文件\n`);
console.log('✅ 图片优化完成!');
console.log(`📁 原始文件已备份到: ${BACKUP_DIR}\n`);
}
main().catch(console.error);