faster smaller
This commit is contained in:
127
scripts/minify.js
Executable file
127
scripts/minify.js
Executable file
@@ -0,0 +1,127 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const { minify } = require('terser');
|
||||
const { minify: minifyHtml } = require('html-minifier-terser');
|
||||
|
||||
const publicDir = path.join(__dirname, '..', 'public');
|
||||
const distDir = path.join(publicDir, 'dist');
|
||||
|
||||
async function minifyJavaScript() {
|
||||
console.log('🔧 Minifying JavaScript...');
|
||||
|
||||
const jsFile = path.join(distDir, 'script.js');
|
||||
|
||||
if (!fs.existsSync(jsFile)) {
|
||||
console.error('❌ script.js not found. Run build first.');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const code = fs.readFileSync(jsFile, 'utf8');
|
||||
|
||||
const result = await minify(code, {
|
||||
compress: {
|
||||
dead_code: true,
|
||||
drop_console: false, // Keep console for debugging
|
||||
drop_debugger: true,
|
||||
keep_classnames: true,
|
||||
keep_fnames: false,
|
||||
passes: 2
|
||||
},
|
||||
mangle: {
|
||||
keep_classnames: true,
|
||||
keep_fnames: false
|
||||
},
|
||||
format: {
|
||||
comments: false
|
||||
},
|
||||
sourceMap: {
|
||||
filename: 'script.js',
|
||||
url: 'script.js.map'
|
||||
}
|
||||
});
|
||||
|
||||
if (result.code) {
|
||||
fs.writeFileSync(jsFile, result.code);
|
||||
if (result.map) {
|
||||
fs.writeFileSync(jsFile + '.map', result.map);
|
||||
}
|
||||
|
||||
const originalSize = Buffer.byteLength(code, 'utf8');
|
||||
const minifiedSize = Buffer.byteLength(result.code, 'utf8');
|
||||
const savings = ((1 - minifiedSize / originalSize) * 100).toFixed(1);
|
||||
|
||||
console.log(`✅ JavaScript minified: ${originalSize} → ${minifiedSize} bytes (${savings}% reduction)`);
|
||||
} else {
|
||||
console.error('❌ Minification failed');
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
async function minifyHTML() {
|
||||
console.log('🔧 Minifying HTML...');
|
||||
|
||||
const htmlFile = path.join(publicDir, 'index.html');
|
||||
|
||||
if (!fs.existsSync(htmlFile)) {
|
||||
console.error('❌ index.html not found');
|
||||
return;
|
||||
}
|
||||
|
||||
const html = fs.readFileSync(htmlFile, 'utf8');
|
||||
|
||||
const minified = await minifyHtml(html, {
|
||||
collapseWhitespace: true,
|
||||
removeComments: true,
|
||||
removeRedundantAttributes: true,
|
||||
removeScriptTypeAttributes: true,
|
||||
removeStyleLinkTypeAttributes: true,
|
||||
useShortDoctype: true,
|
||||
minifyCSS: true,
|
||||
minifyJS: false, // Don't minify inline JS (we handle it separately)
|
||||
keepClosingSlash: true
|
||||
});
|
||||
|
||||
const originalSize = Buffer.byteLength(html, 'utf8');
|
||||
const minifiedSize = Buffer.byteLength(minified, 'utf8');
|
||||
const savings = ((1 - minifiedSize / originalSize) * 100).toFixed(1);
|
||||
|
||||
// Save to dist folder
|
||||
fs.writeFileSync(path.join(publicDir, 'index.min.html'), minified);
|
||||
|
||||
console.log(`✅ HTML minified: ${originalSize} → ${minifiedSize} bytes (${savings}% reduction)`);
|
||||
}
|
||||
|
||||
async function minifyCSS() {
|
||||
console.log('🔧 Checking CSS...');
|
||||
|
||||
const cssFile = path.join(publicDir, 'style.css');
|
||||
|
||||
if (!fs.existsSync(cssFile)) {
|
||||
console.log('ℹ️ No CSS file to minify');
|
||||
return;
|
||||
}
|
||||
|
||||
const css = fs.readFileSync(cssFile, 'utf8');
|
||||
const originalSize = Buffer.byteLength(css, 'utf8');
|
||||
|
||||
console.log(`ℹ️ CSS size: ${originalSize} bytes (already optimized)`);
|
||||
}
|
||||
|
||||
async function main() {
|
||||
console.log('🚀 Starting minification process...\n');
|
||||
|
||||
try {
|
||||
await minifyJavaScript();
|
||||
await minifyHTML();
|
||||
await minifyCSS();
|
||||
|
||||
console.log('\n✨ All files minified successfully!');
|
||||
} catch (error) {
|
||||
console.error('❌ Minification error:', error);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
main();
|
||||
Reference in New Issue
Block a user