104 lines
2.6 KiB
JavaScript
104 lines
2.6 KiB
JavaScript
|
|
#!/usr/bin/env node
|
|||
|
|
|
|||
|
|
const fs = require('fs');
|
|||
|
|
const path = require('path');
|
|||
|
|
const { optimize } = require('svgo');
|
|||
|
|
|
|||
|
|
// SVG优化配置
|
|||
|
|
const svgoConfig = {
|
|||
|
|
multipass: true,
|
|||
|
|
plugins: [
|
|||
|
|
{
|
|||
|
|
name: 'preset-default',
|
|||
|
|
params: {
|
|||
|
|
overrides: {
|
|||
|
|
removeViewBox: false,
|
|||
|
|
cleanupIds: false,
|
|||
|
|
},
|
|||
|
|
},
|
|||
|
|
},
|
|||
|
|
'removeDimensions',
|
|||
|
|
'removeStyleElement',
|
|||
|
|
'removeScriptElement',
|
|||
|
|
'removeComments',
|
|||
|
|
'removeMetadata',
|
|||
|
|
'removeEditorsNSData',
|
|||
|
|
'cleanupListOfValues',
|
|||
|
|
'convertStyleToAttrs',
|
|||
|
|
'removeEmptyContainers',
|
|||
|
|
'mergePaths',
|
|||
|
|
'convertShapeToPath',
|
|||
|
|
'sortAttrs',
|
|||
|
|
'removeDimensions',
|
|||
|
|
],
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// 递归遍历目录
|
|||
|
|
function walkDir(dir, callback) {
|
|||
|
|
fs.readdirSync(dir).forEach(file => {
|
|||
|
|
const filePath = path.join(dir, file);
|
|||
|
|
const stat = fs.statSync(filePath);
|
|||
|
|
|
|||
|
|
if (stat.isDirectory()) {
|
|||
|
|
walkDir(filePath, callback);
|
|||
|
|
} else if (path.extname(file) === '.svg') {
|
|||
|
|
callback(filePath);
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 优化单个SVG文件
|
|||
|
|
function optimizeSvg(filePath) {
|
|||
|
|
try {
|
|||
|
|
const svgContent = fs.readFileSync(filePath, 'utf8');
|
|||
|
|
const originalSize = Buffer.byteLength(svgContent, 'utf8');
|
|||
|
|
|
|||
|
|
const result = optimize(svgContent, {
|
|||
|
|
path: filePath,
|
|||
|
|
...svgoConfig,
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
const optimizedSize = Buffer.byteLength(result.data, 'utf8');
|
|||
|
|
const savings = ((1 - optimizedSize / originalSize) * 100).toFixed(1);
|
|||
|
|
|
|||
|
|
fs.writeFileSync(filePath, result.data);
|
|||
|
|
|
|||
|
|
console.log(`✓ ${path.relative(process.cwd(), filePath)}: ${originalSize}B → ${optimizedSize}B (节省 ${savings}%)`);
|
|||
|
|
|
|||
|
|
return { originalSize, optimizedSize, savings: parseFloat(savings) };
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error(`✗ 处理文件失败: ${filePath}`, error.message);
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 主函数
|
|||
|
|
function main() {
|
|||
|
|
const publicDir = path.join(process.cwd(), 'public');
|
|||
|
|
|
|||
|
|
console.log('开始优化SVG文件...\n');
|
|||
|
|
|
|||
|
|
let totalOriginal = 0;
|
|||
|
|
let totalOptimized = 0;
|
|||
|
|
let fileCount = 0;
|
|||
|
|
|
|||
|
|
walkDir(publicDir, (filePath) => {
|
|||
|
|
const result = optimizeSvg(filePath);
|
|||
|
|
if (result) {
|
|||
|
|
totalOriginal += result.originalSize;
|
|||
|
|
totalOptimized += result.optimizedSize;
|
|||
|
|
fileCount++;
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
const totalSavings = ((1 - totalOptimized / totalOriginal) * 100).toFixed(1);
|
|||
|
|
|
|||
|
|
console.log('\n优化完成!');
|
|||
|
|
console.log(`处理文件: ${fileCount} 个`);
|
|||
|
|
console.log(`原始大小: ${(totalOriginal / 1024).toFixed(2)} KB`);
|
|||
|
|
console.log(`优化后: ${(totalOptimized / 1024).toFixed(2)} KB`);
|
|||
|
|
console.log(`总共节省: ${totalSavings}% (${((totalOriginal - totalOptimized) / 1024).toFixed(2)} KB)`);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
main();
|