| import esbuild from 'esbuild' |
| import fs from 'node:fs' |
| import zlib from 'node:zlib' |
| import path from 'node:path' |
| import { fileURLToPath } from 'node:url' |
|
|
| const root = path.join(path.dirname(fileURLToPath(import.meta.url)), '..') |
| const pub = path.join(root, 'public') |
|
|
| fs.mkdirSync(pub, { recursive: true }) |
|
|
| |
| |
| const buildId = String(Date.now()) |
|
|
| await esbuild.build({ |
| entryPoints: [path.join(root, 'client/src/doc.js'), path.join(root, 'client/src/home.js')], |
| bundle: true, |
| minify: true, |
| format: 'iife', |
| outdir: pub, |
| define: { 'process.env.NODE_ENV': '"production"', __BUILD_ID__: JSON.stringify(buildId) }, |
| logLevel: 'info', |
| }) |
|
|
| |
| |
| |
| |
| for (const f of ['doc.html', 'index.html', 'app.css']) { |
| let body = fs.readFileSync(path.join(root, 'client', f), 'utf8') |
| if (f.endsWith('.html')) { |
| body = body |
| .replace(/(src|href)="\/(doc|home)\.js"/g, `$1="/$2.js?v=${buildId}"`) |
| .replace(/href="\/app\.css"/g, `href="/app.css?v=${buildId}"`) |
| } |
| fs.writeFileSync(path.join(pub, f), body) |
| } |
| |
| fs.mkdirSync(path.join(pub, 'fonts'), { recursive: true }) |
| for (const f of fs.readdirSync(path.join(root, 'client/fonts'))) { |
| fs.copyFileSync(path.join(root, 'client/fonts', f), path.join(pub, 'fonts', f)) |
| } |
|
|
| |
| |
| |
| |
| |
| const katexDist = path.join(root, 'node_modules/katex/dist') |
| fs.copyFileSync(path.join(katexDist, 'katex.min.js'), path.join(pub, 'katex.js')) |
| fs.copyFileSync(path.join(katexDist, 'katex.min.css'), path.join(pub, 'katex.css')) |
| for (const f of fs.readdirSync(path.join(katexDist, 'fonts'))) { |
| if (f.endsWith('.woff2')) fs.copyFileSync(path.join(katexDist, 'fonts', f), path.join(pub, 'fonts', f)) |
| } |
|
|
| fs.writeFileSync(path.join(pub, 'build-id'), buildId) |
|
|
| |
| |
| |
| |
| const compressed = [] |
| for (const f of fs.readdirSync(pub)) { |
| if (!/\.(js|css)$/.test(f)) continue |
| const raw = fs.readFileSync(path.join(pub, f)) |
| const br = zlib.brotliCompressSync(raw, { |
| params: { |
| [zlib.constants.BROTLI_PARAM_QUALITY]: zlib.constants.BROTLI_MAX_QUALITY, |
| [zlib.constants.BROTLI_PARAM_SIZE_HINT]: raw.length, |
| }, |
| }) |
| const gz = zlib.gzipSync(raw, { level: zlib.constants.Z_BEST_COMPRESSION }) |
| fs.writeFileSync(path.join(pub, f + '.br'), br) |
| fs.writeFileSync(path.join(pub, f + '.gz'), gz) |
| compressed.push(`${f} ${kb(raw.length)}K -> br ${kb(br.length)}K / gz ${kb(gz.length)}K`) |
| } |
| console.log('build done ->', pub, 'build-id', buildId) |
| for (const line of compressed) console.log(' ', line) |
|
|
| function kb(n) { |
| return Math.round(n / 1024) |
| } |
|
|