/** * Build script: copy src → dist, minify JS/CSS, inline critical CSS (Beasties). * Run with: pnpm build */ import { rmSync, mkdirSync, readFileSync, writeFileSync, cpSync, readdirSync } from 'fs' import { join, dirname, extname } from 'path' import { fileURLToPath } from 'url' import Beasties from 'beasties' import { minify as minifyJs } from 'terser' import CleanCSS from 'clean-css' const __dirname = dirname(fileURLToPath(import.meta.url)) const root = join(__dirname, '..') const srcDir = join(root, 'src') const distDir = join(root, 'dist') function getFiles(dir, files = []) { const entries = readdirSync(dir, { withFileTypes: true }) for (const e of entries) { const full = join(dir, e.name) if (e.isDirectory()) getFiles(full, files) else files.push(full) } return files } async function main() { // 1. Clean and copy src → dist rmSync(distDir, { recursive: true, force: true }) mkdirSync(distDir, { recursive: true }) cpSync(srcDir, distDir, { recursive: true }) const distFiles = getFiles(distDir) // 2. Minify JS const jsFiles = distFiles.filter((f) => extname(f) === '.js') for (const f of jsFiles) { const code = readFileSync(f, 'utf8') const result = await minifyJs(code, { format: { comments: false } }) if (result.code) writeFileSync(f, result.code) } // 3. Minify CSS const cleanCss = new CleanCSS({ level: 2 }) const cssFiles = distFiles.filter((f) => extname(f) === '.css') for (const f of cssFiles) { const code = readFileSync(f, 'utf8') const result = cleanCss.minify(code) if (!result.errors.length) writeFileSync(f, result.styles) } // 4. Inline critical CSS with Beasties for all HTML files (no browser; works in CI) const htmlFiles = distFiles.filter((f) => extname(f) === '.html') const beasties = new Beasties({ path: distDir, preload: 'default', logLevel: 'warn' }) for (const htmlFile of htmlFiles) { const html = readFileSync(htmlFile, 'utf8') const inlined = await beasties.process(html) writeFileSync(htmlFile, inlined) } console.log('Build complete: dist/') } main().catch((err) => { console.error(err) process.exit(1) })