130 lines
3.5 KiB
JavaScript
130 lines
3.5 KiB
JavaScript
// 图片优化脚本 - 使用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);
|