It appears you have a well-structured Git repository with various files, including SVG icons and HTML documents. Here's a brief overview:

This commit is contained in:
2025-06-11 09:05:15 +02:00
parent 36c2466e53
commit 6d6aa954dd
15556 changed files with 1076330 additions and 1 deletions

View File

@ -0,0 +1,238 @@
#!/usr/bin/env node
/**
* Asset-Komprimierungsskript für MYP Backend
* Komprimiert CSS und JS-Dateien mit gzip für bessere Performance
*/
const fs = require('fs');
const path = require('path');
const zlib = require('zlib');
const { promisify } = require('util');
const gzip = promisify(zlib.gzip);
const readFile = promisify(fs.readFile);
const writeFile = promisify(fs.writeFile);
const stat = promisify(fs.stat);
// Konfiguration
const STATIC_DIR = path.join(__dirname, '..', 'static');
const COMPRESSION_LEVEL = 9; // Maximale Komprimierung
// Dateierweiterungen die komprimiert werden sollen
const COMPRESSIBLE_EXTENSIONS = ['.css', '.js', '.html', '.svg', '.json'];
// Mindestgröße für Komprimierung (in Bytes)
const MIN_SIZE_FOR_COMPRESSION = 1024; // 1KB
/**
* Komprimiert eine einzelne Datei
*/
async function compressFile(filePath) {
try {
const stats = await stat(filePath);
// Überspringe kleine Dateien
if (stats.size < MIN_SIZE_FOR_COMPRESSION) {
console.log(`⏭️ Überspringe ${filePath} (zu klein: ${stats.size} bytes)`);
return;
}
const data = await readFile(filePath);
const compressed = await gzip(data, { level: COMPRESSION_LEVEL });
const gzPath = filePath + '.gz';
await writeFile(gzPath, compressed);
const compressionRatio = ((stats.size - compressed.length) / stats.size * 100).toFixed(1);
const originalSize = formatBytes(stats.size);
const compressedSize = formatBytes(compressed.length);
console.log(`${path.basename(filePath)}: ${originalSize}${compressedSize} (-${compressionRatio}%)`);
} catch (error) {
console.error(`❌ Fehler beim Komprimieren von ${filePath}:`, error.message);
}
}
/**
* Durchsucht Verzeichnis rekursiv nach komprimierbaren Dateien
*/
async function findCompressibleFiles(dir) {
const files = [];
try {
const entries = await fs.promises.readdir(dir, { withFileTypes: true });
for (const entry of entries) {
const fullPath = path.join(dir, entry.name);
if (entry.isDirectory()) {
// Rekursiv in Unterverzeichnisse
const subFiles = await findCompressibleFiles(fullPath);
files.push(...subFiles);
} else if (entry.isFile()) {
const ext = path.extname(entry.name);
// Überspringe bereits komprimierte Dateien
if (entry.name.endsWith('.gz')) {
continue;
}
// Prüfe ob Dateiart komprimierbar ist
if (COMPRESSIBLE_EXTENSIONS.includes(ext)) {
files.push(fullPath);
}
}
}
} catch (error) {
console.warn(`⚠️ Kann Verzeichnis nicht lesen: ${dir} - ${error.message}`);
}
return files;
}
/**
* Formatiert Byte-Größen lesbar
*/
function formatBytes(bytes) {
if (bytes === 0) return '0 B';
const k = 1024;
const sizes = ['B', 'KB', 'MB', 'GB'];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(1)) + ' ' + sizes[i];
}
/**
* Bereinigt alte .gz-Dateien
*/
async function cleanupOldGzFiles(dir) {
try {
const entries = await fs.promises.readdir(dir, { withFileTypes: true });
let cleaned = 0;
for (const entry of entries) {
const fullPath = path.join(dir, entry.name);
if (entry.isDirectory()) {
cleaned += await cleanupOldGzFiles(fullPath);
} else if (entry.name.endsWith('.gz')) {
const originalPath = fullPath.slice(0, -3); // Entferne .gz
try {
await stat(originalPath);
// Original existiert, behalte .gz
} catch (error) {
// Original existiert nicht, lösche .gz
await fs.promises.unlink(fullPath);
console.log(`🗑️ Bereinigt: ${entry.name}`);
cleaned++;
}
}
}
return cleaned;
} catch (error) {
console.warn(`⚠️ Fehler beim Bereinigen von ${dir}: ${error.message}`);
return 0;
}
}
/**
* Hauptfunktion
*/
async function main() {
console.log('🚀 MYP Asset-Komprimierung gestartet...\n');
const startTime = Date.now();
// Bereinige alte .gz-Dateien
console.log('🧹 Bereinige alte komprimierte Dateien...');
const cleanedFiles = await cleanupOldGzFiles(STATIC_DIR);
if (cleanedFiles > 0) {
console.log(`${cleanedFiles} verwaiste .gz-Dateien bereinigt\n`);
} else {
console.log('✅ Keine Bereinigung erforderlich\n');
}
// Finde alle komprimierbaren Dateien
console.log('🔍 Suche nach komprimierbaren Dateien...');
const files = await findCompressibleFiles(STATIC_DIR);
console.log(`📁 ${files.length} komprimierbare Dateien gefunden\n`);
if (files.length === 0) {
console.log(' Keine Dateien zum Komprimieren gefunden.');
return;
}
// Komprimiere alle Dateien parallel (aber begrenzt)
console.log('📦 Komprimiere Dateien...');
const BATCH_SIZE = 10; // Maximale parallele Verarbeitung
let totalOriginalSize = 0;
let totalCompressedSize = 0;
let processedFiles = 0;
for (let i = 0; i < files.length; i += BATCH_SIZE) {
const batch = files.slice(i, i + BATCH_SIZE);
const promises = batch.map(async (file) => {
try {
const stats = await stat(file);
if (stats.size >= MIN_SIZE_FOR_COMPRESSION) {
const data = await readFile(file);
const compressed = await gzip(data, { level: COMPRESSION_LEVEL });
await writeFile(file + '.gz', compressed);
totalOriginalSize += stats.size;
totalCompressedSize += compressed.length;
processedFiles++;
return {
file: path.basename(file),
original: stats.size,
compressed: compressed.length
};
}
} catch (error) {
console.error(`${path.basename(file)}: ${error.message}`);
return null;
}
});
const results = await Promise.all(promises);
// Zeige Fortschritt für diese Batch
results.filter(r => r).forEach(result => {
const ratio = ((result.original - result.compressed) / result.original * 100).toFixed(1);
console.log(`${result.file}: ${formatBytes(result.original)}${formatBytes(result.compressed)} (-${ratio}%)`);
});
}
const endTime = Date.now();
const duration = ((endTime - startTime) / 1000).toFixed(2);
console.log('\n🎉 Komprimierung abgeschlossen!');
console.log(`📊 Statistiken:`);
console.log(` • Verarbeitete Dateien: ${processedFiles}`);
console.log(` • Originalgröße: ${formatBytes(totalOriginalSize)}`);
console.log(` • Komprimierte Größe: ${formatBytes(totalCompressedSize)}`);
if (totalOriginalSize > 0) {
const totalSavings = ((totalOriginalSize - totalCompressedSize) / totalOriginalSize * 100).toFixed(1);
console.log(` • Gesamt-Einsparung: ${formatBytes(totalOriginalSize - totalCompressedSize)} (-${totalSavings}%)`);
}
console.log(` • Dauer: ${duration}s`);
console.log('\n💡 Tipp: Verwenden Sie gzip-komprimierte Dateien mit Flask-Compress für optimale Performance!');
}
// Führe Skript nur aus wenn direkt aufgerufen
if (require.main === module) {
main().catch(error => {
console.error('💥 Kritischer Fehler:', error);
process.exit(1);
});
}
module.exports = { compressFile, findCompressibleFiles, cleanupOldGzFiles };