feat: Build-System für Obfuscation und Minification hinzugefügt
- package.json mit Build-Dependencies - Build-Script für JavaScript Obfuscation (javascript-obfuscator) - CSS Minification (clean-css) - Automatisches Kopieren der PHP-Dateien
This commit is contained in:
293
scripts/build.js
Normal file
293
scripts/build.js
Normal file
@@ -0,0 +1,293 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* HexaHost.de Build Script
|
||||
*
|
||||
* Obfusciert JavaScript und minifiziert CSS für die Produktion
|
||||
*
|
||||
* Verwendung:
|
||||
* npm run build - Alles bauen
|
||||
* npm run build:js - Nur JavaScript
|
||||
* npm run build:css - Nur CSS
|
||||
*/
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const JavaScriptObfuscator = require('javascript-obfuscator');
|
||||
const CleanCSS = require('clean-css');
|
||||
|
||||
// Konfiguration
|
||||
const config = {
|
||||
srcDir: path.join(__dirname, '..'),
|
||||
distDir: path.join(__dirname, '..', 'dist'),
|
||||
|
||||
// JavaScript-Dateien zum Obfuscieren
|
||||
jsFiles: [
|
||||
'assets/js/main.js',
|
||||
'assets/js/contact.js',
|
||||
'assets/js/cookie-consent.js'
|
||||
],
|
||||
|
||||
// CSS-Dateien zum Minifizieren
|
||||
cssFiles: [
|
||||
'assets/css/style.css'
|
||||
],
|
||||
|
||||
// PHP-Dateien (nur kopieren)
|
||||
phpFiles: [
|
||||
'config/config.php',
|
||||
'config/mail-config.php',
|
||||
'includes/header.php',
|
||||
'includes/footer.php',
|
||||
'includes/functions.php'
|
||||
],
|
||||
|
||||
// JavaScript Obfuscator Optionen
|
||||
jsObfuscatorOptions: {
|
||||
compact: true,
|
||||
controlFlowFlattening: true,
|
||||
controlFlowFlatteningThreshold: 0.7,
|
||||
deadCodeInjection: true,
|
||||
deadCodeInjectionThreshold: 0.4,
|
||||
debugProtection: false,
|
||||
disableConsoleOutput: true,
|
||||
identifierNamesGenerator: 'hexadecimal',
|
||||
log: false,
|
||||
numbersToExpressions: true,
|
||||
renameGlobals: false,
|
||||
selfDefending: true,
|
||||
simplify: true,
|
||||
splitStrings: true,
|
||||
splitStringsChunkLength: 10,
|
||||
stringArray: true,
|
||||
stringArrayCallsTransform: true,
|
||||
stringArrayEncoding: ['base64'],
|
||||
stringArrayIndexShift: true,
|
||||
stringArrayRotate: true,
|
||||
stringArrayShuffle: true,
|
||||
stringArrayWrappersCount: 2,
|
||||
stringArrayWrappersChainedCalls: true,
|
||||
stringArrayWrappersParametersMaxCount: 4,
|
||||
stringArrayWrappersType: 'function',
|
||||
stringArrayThreshold: 0.75,
|
||||
transformObjectKeys: true,
|
||||
unicodeEscapeSequence: false
|
||||
},
|
||||
|
||||
// Clean-CSS Optionen
|
||||
cssMinifyOptions: {
|
||||
level: {
|
||||
1: {
|
||||
specialComments: 0
|
||||
},
|
||||
2: {
|
||||
mergeMedia: true,
|
||||
removeEmpty: true,
|
||||
removeDuplicateFontRules: true,
|
||||
removeDuplicateMediaBlocks: true,
|
||||
removeDuplicateRules: true
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Hilfsfunktionen
|
||||
function ensureDir(dir) {
|
||||
if (!fs.existsSync(dir)) {
|
||||
fs.mkdirSync(dir, { recursive: true });
|
||||
}
|
||||
}
|
||||
|
||||
function copyFile(src, dest) {
|
||||
ensureDir(path.dirname(dest));
|
||||
fs.copyFileSync(src, dest);
|
||||
}
|
||||
|
||||
function formatBytes(bytes) {
|
||||
if (bytes === 0) return '0 Bytes';
|
||||
const k = 1024;
|
||||
const sizes = ['Bytes', 'KB', 'MB'];
|
||||
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
||||
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
|
||||
}
|
||||
|
||||
function getCompressionRatio(original, compressed) {
|
||||
return ((1 - compressed / original) * 100).toFixed(1);
|
||||
}
|
||||
|
||||
// JavaScript obfuscieren
|
||||
function obfuscateJS(filePath) {
|
||||
const srcPath = path.join(config.srcDir, filePath);
|
||||
const destPath = path.join(config.distDir, filePath);
|
||||
|
||||
if (!fs.existsSync(srcPath)) {
|
||||
console.log(` ⚠️ Datei nicht gefunden: ${filePath}`);
|
||||
return null;
|
||||
}
|
||||
|
||||
const originalCode = fs.readFileSync(srcPath, 'utf8');
|
||||
const originalSize = Buffer.byteLength(originalCode, 'utf8');
|
||||
|
||||
try {
|
||||
const obfuscatedCode = JavaScriptObfuscator.obfuscate(
|
||||
originalCode,
|
||||
config.jsObfuscatorOptions
|
||||
).getObfuscatedCode();
|
||||
|
||||
const obfuscatedSize = Buffer.byteLength(obfuscatedCode, 'utf8');
|
||||
|
||||
ensureDir(path.dirname(destPath));
|
||||
fs.writeFileSync(destPath, obfuscatedCode);
|
||||
|
||||
return {
|
||||
file: filePath,
|
||||
originalSize,
|
||||
newSize: obfuscatedSize,
|
||||
ratio: getCompressionRatio(originalSize, obfuscatedSize)
|
||||
};
|
||||
} catch (error) {
|
||||
console.log(` ❌ Fehler bei ${filePath}: ${error.message}`);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// CSS minifizieren
|
||||
function minifyCSS(filePath) {
|
||||
const srcPath = path.join(config.srcDir, filePath);
|
||||
const destPath = path.join(config.distDir, filePath);
|
||||
|
||||
if (!fs.existsSync(srcPath)) {
|
||||
console.log(` ⚠️ Datei nicht gefunden: ${filePath}`);
|
||||
return null;
|
||||
}
|
||||
|
||||
const originalCode = fs.readFileSync(srcPath, 'utf8');
|
||||
const originalSize = Buffer.byteLength(originalCode, 'utf8');
|
||||
|
||||
try {
|
||||
const minified = new CleanCSS(config.cssMinifyOptions).minify(originalCode);
|
||||
|
||||
if (minified.errors.length > 0) {
|
||||
console.log(` ❌ Fehler bei ${filePath}: ${minified.errors.join(', ')}`);
|
||||
return null;
|
||||
}
|
||||
|
||||
const minifiedSize = Buffer.byteLength(minified.styles, 'utf8');
|
||||
|
||||
ensureDir(path.dirname(destPath));
|
||||
fs.writeFileSync(destPath, minified.styles);
|
||||
|
||||
return {
|
||||
file: filePath,
|
||||
originalSize,
|
||||
newSize: minifiedSize,
|
||||
ratio: getCompressionRatio(originalSize, minifiedSize)
|
||||
};
|
||||
} catch (error) {
|
||||
console.log(` ❌ Fehler bei ${filePath}: ${error.message}`);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// PHP-Dateien kopieren (keine Obfuscation)
|
||||
function copyPHP(filePath) {
|
||||
const srcPath = path.join(config.srcDir, filePath);
|
||||
const destPath = path.join(config.distDir, filePath);
|
||||
|
||||
if (!fs.existsSync(srcPath)) {
|
||||
console.log(` ⚠️ Datei nicht gefunden: ${filePath}`);
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
copyFile(srcPath, destPath);
|
||||
const size = fs.statSync(srcPath).size;
|
||||
|
||||
return {
|
||||
file: filePath,
|
||||
originalSize: size,
|
||||
newSize: size,
|
||||
ratio: '0'
|
||||
};
|
||||
} catch (error) {
|
||||
console.log(` ❌ Fehler bei ${filePath}: ${error.message}`);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// Hauptfunktion
|
||||
function build() {
|
||||
const args = process.argv.slice(2);
|
||||
const jsOnly = args.includes('--js-only');
|
||||
const cssOnly = args.includes('--css-only');
|
||||
|
||||
console.log('\n╔════════════════════════════════════════════════════════════╗');
|
||||
console.log('║ HexaHost.de - Build System ║');
|
||||
console.log('║ Obfuscation & Minification ║');
|
||||
console.log('╚════════════════════════════════════════════════════════════╝\n');
|
||||
|
||||
// dist-Verzeichnis erstellen/leeren
|
||||
if (fs.existsSync(config.distDir)) {
|
||||
fs.rmSync(config.distDir, { recursive: true });
|
||||
}
|
||||
ensureDir(config.distDir);
|
||||
|
||||
const results = [];
|
||||
|
||||
// JavaScript obfuscieren
|
||||
if (!cssOnly) {
|
||||
console.log('📦 JavaScript obfuscieren...\n');
|
||||
config.jsFiles.forEach(file => {
|
||||
process.stdout.write(` → ${file}... `);
|
||||
const result = obfuscateJS(file);
|
||||
if (result) {
|
||||
console.log(`✓ (${formatBytes(result.originalSize)} → ${formatBytes(result.newSize)}, -${result.ratio}%)`);
|
||||
results.push(result);
|
||||
}
|
||||
});
|
||||
console.log();
|
||||
}
|
||||
|
||||
// CSS minifizieren
|
||||
if (!jsOnly) {
|
||||
console.log('🎨 CSS minifizieren...\n');
|
||||
config.cssFiles.forEach(file => {
|
||||
process.stdout.write(` → ${file}... `);
|
||||
const result = minifyCSS(file);
|
||||
if (result) {
|
||||
console.log(`✓ (${formatBytes(result.originalSize)} → ${formatBytes(result.newSize)}, -${result.ratio}%)`);
|
||||
results.push(result);
|
||||
}
|
||||
});
|
||||
console.log();
|
||||
}
|
||||
|
||||
// PHP-Dateien kopieren
|
||||
if (!jsOnly && !cssOnly) {
|
||||
console.log('📄 PHP-Dateien kopieren...\n');
|
||||
config.phpFiles.forEach(file => {
|
||||
process.stdout.write(` → ${file}... `);
|
||||
const result = copyPHP(file);
|
||||
if (result) {
|
||||
console.log(`✓ (${formatBytes(result.originalSize)})`);
|
||||
results.push(result);
|
||||
}
|
||||
});
|
||||
console.log();
|
||||
}
|
||||
|
||||
// Zusammenfassung
|
||||
const totalOriginal = results.reduce((sum, r) => sum + r.originalSize, 0);
|
||||
const totalNew = results.reduce((sum, r) => sum + r.newSize, 0);
|
||||
|
||||
console.log('═══════════════════════════════════════════════════════════════');
|
||||
console.log(`✅ Build abgeschlossen!`);
|
||||
console.log(` Dateien: ${results.length}`);
|
||||
console.log(` Original: ${formatBytes(totalOriginal)}`);
|
||||
console.log(` Optimiert: ${formatBytes(totalNew)}`);
|
||||
console.log(` Ersparnis: ${formatBytes(totalOriginal - totalNew)} (${getCompressionRatio(totalOriginal, totalNew)}%)`);
|
||||
console.log(` Ausgabe: ${config.distDir}`);
|
||||
console.log('═══════════════════════════════════════════════════════════════\n');
|
||||
}
|
||||
|
||||
// Build starten
|
||||
build();
|
||||
Reference in New Issue
Block a user