codtracker-js/debug/build_v2.js
2025-03-29 15:55:06 -04:00

234 lines
6.4 KiB
JavaScript

const fs = require('fs');
const path = require('path');
const glob = require('glob');
const terser = require('terser');
const csso = require('csso');
const htmlmin = require('html-minifier');
// Configuration
const config = {
rootJs: {
src: './*.js',
exclude: './*.min.js',
outputExt: '.min.js'
},
js: {
src: 'src/**/*.js',
exclude: 'src/**/*.min.js',
outputExt: '.min.js'
},
css: {
src: 'src/**/*.css',
exclude: 'src/**/*.min.css',
outputExt: '.min.css'
},
json: {
src: 'src/**/*.json'
},
html: {
src: 'src/**/*.html'
},
images: {
src: 'src/**/*.+(png|jpg|jpeg|gif|svg|ico)'
}
};
// Ensure directory exists
function ensureDirectoryExistence(filePath) {
const dirname = path.dirname(filePath);
if (fs.existsSync(dirname)) return;
ensureDirectoryExistence(dirname);
fs.mkdirSync(dirname);
}
// Clean public directory
function cleanPublicDir() {
console.log('Cleaning public directory...');
if (fs.existsSync('public')) {
fs.rmSync('public', { recursive: true, force: true });
}
fs.mkdirSync('public');
console.log('✓ Public directory cleaned');
}
// Create output path preserving directory structure
function createOutputPath(file, baseDir, outputExt = null) {
// Get relative path from the source root
const relativePath = path.relative(baseDir, file);
// Create public path with the same relative structure
let outputPath = path.join('public', relativePath);
// Apply output extension if provided
if (outputExt) {
outputPath = outputPath.replace(path.extname(outputPath), outputExt);
}
return outputPath;
}
// Minify JavaScript files
async function minifyJS() {
console.log('Minifying JavaScript files...');
// Minify root-level JS files (like app.js)
const rootFiles = glob.sync(config.rootJs.src, { ignore: config.rootJs.exclude });
for (const file of rootFiles) {
// Skip already minified files and module files
if (file.endsWith('.min.js') || file === 'build.js') continue;
const content = fs.readFileSync(file, 'utf8');
const result = await terser.minify(content, {
compress: true,
mangle: true
});
const outputPath = createOutputPath(file, '.', config.rootJs.outputExt);
ensureDirectoryExistence(outputPath);
fs.writeFileSync(outputPath, result.code);
console.log(`✓ Minified: ${file} -> ${outputPath}`);
}
// Minify JavaScript files in src directory
const srcFiles = glob.sync(config.js.src, { ignore: config.js.exclude });
for (const file of srcFiles) {
// Skip already minified files, type definition, and map files
if (file.endsWith('.min.js') || file.endsWith('.d.ts') || file.endsWith('.map')) continue;
const content = fs.readFileSync(file, 'utf8');
const result = await terser.minify(content, {
compress: true,
mangle: true
});
const outputPath = createOutputPath(file, '.', config.js.outputExt);
ensureDirectoryExistence(outputPath);
fs.writeFileSync(outputPath, result.code);
console.log(`✓ Minified: ${file} -> ${outputPath}`);
}
}
// Minify CSS files
function minifyCSS() {
console.log('Minifying CSS files...');
const files = glob.sync(config.css.src, { ignore: config.css.exclude });
for (const file of files) {
if (file.endsWith('.min.css')) continue;
const content = fs.readFileSync(file, 'utf8');
const result = csso.minify(content);
const outputPath = createOutputPath(file, '.', config.css.outputExt);
ensureDirectoryExistence(outputPath);
fs.writeFileSync(outputPath, result.css);
console.log(`✓ Minified: ${file} -> ${outputPath}`);
}
}
// Minify JSON files
function minifyJSON() {
console.log('Minifying JSON files...');
const files = glob.sync(config.json.src);
for (const file of files) {
const content = fs.readFileSync(file, 'utf8');
const jsonData = JSON.parse(content);
const minified = JSON.stringify(jsonData);
const outputPath = createOutputPath(file, '.');
ensureDirectoryExistence(outputPath);
fs.writeFileSync(outputPath, minified);
console.log(`✓ Minified: ${file} -> ${outputPath}`);
}
}
// Minify HTML files and update references
function minifyHTML() {
console.log('Minifying HTML files...');
const files = glob.sync(config.html.src);
for (const file of files) {
let content = fs.readFileSync(file, 'utf8');
// Update JS references to minified versions, preserving directory structure
content = content.replace(/src=["'](.+?)\.js["']/g, (match, p1) => {
return `src="${p1}.min.js"`;
});
// Update CSS references to minified versions, preserving directory structure
content = content.replace(/href=["'](.+?)\.css["']/g, (match, p1) => {
return `href="${p1}.min.css"`;
});
// Minify HTML
const minified = htmlmin.minify(content, {
collapseWhitespace: true,
removeComments: true,
minifyJS: true,
minifyCSS: true,
removeRedundantAttributes: true,
removeEmptyAttributes: true,
removeOptionalTags: true
});
const outputPath = createOutputPath(file, '.');
ensureDirectoryExistence(outputPath);
fs.writeFileSync(outputPath, minified);
console.log(`✓ Minified: ${file} -> ${outputPath}`);
}
}
// Copy images
function copyImages() {
console.log('Copying images...');
const files = glob.sync(config.images.src);
for (const file of files) {
const outputPath = createOutputPath(file, '.');
ensureDirectoryExistence(outputPath);
fs.copyFileSync(file, outputPath);
console.log(`✓ Copied: ${file} -> ${outputPath}`);
}
}
// Copy other files like README.md
function copyMiscFiles() {
console.log('Copying miscellaneous files...');
const filesToCopy = [
'README.md',
'package.json',
'package-lock.json'
];
for (const file of filesToCopy) {
if (fs.existsSync(file)) {
const outputPath = path.join('public', file);
fs.copyFileSync(file, outputPath);
console.log(`✓ Copied: ${file} -> ${outputPath}`);
}
}
}
// Main function
async function build() {
console.log('Starting build process...');
cleanPublicDir();
await minifyJS();
minifyCSS();
minifyJSON();
minifyHTML();
copyImages();
copyMiscFiles();
console.log('Build completed successfully!');
}
// Run the build
build().catch(err => {
console.error('Build failed:', err);
process.exit(1);
});