Initial release
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
// release/esbuild.config.mjs - Bundle the HOT-Step CPP server for portable distribution
|
||||
//
|
||||
// Usage: node release/esbuild.config.mjs
|
||||
//
|
||||
// Produces: release/staging/server/server.mjs
|
||||
// - All TypeScript/JS source bundled into a single ESM file
|
||||
// - better-sqlite3 marked external (native addon, can't be bundled)
|
||||
// - ffmpeg-static excluded (replaced by config-based path resolution)
|
||||
// - model-registry.json loaded via fs.readFileSync (not bundled inline)
|
||||
|
||||
import esbuild from 'esbuild';
|
||||
import path from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
import { builtinModules } from 'module';
|
||||
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||
const projectRoot = path.resolve(__dirname, '..');
|
||||
|
||||
// Build complete list of Node.js built-in modules (with and without node: prefix)
|
||||
const nodeExternals = [
|
||||
...builtinModules,
|
||||
...builtinModules.map(m => `node:${m}`),
|
||||
];
|
||||
|
||||
const result = await esbuild.build({
|
||||
entryPoints: [path.join(projectRoot, 'server/src/index.ts')],
|
||||
bundle: true,
|
||||
platform: 'node',
|
||||
target: 'node22',
|
||||
format: 'esm',
|
||||
outfile: path.join(projectRoot, 'release/staging/server/server.mjs'),
|
||||
|
||||
// External: native addon + all Node.js built-in modules
|
||||
// Node builtins must be external because esbuild's ESM CJS-compat shim
|
||||
// can't handle dynamic require("node:events") from Express and other CJS deps.
|
||||
external: ['better-sqlite3', ...nodeExternals],
|
||||
|
||||
// Plugin: redirect browser polyfill packages (with trailing slash) to Node.js
|
||||
// built-ins. e.g. require('process/') -> require('process')
|
||||
plugins: [{
|
||||
name: 'node-polyfill-redirect',
|
||||
setup(build) {
|
||||
// Match requires like 'process/', 'string_decoder/', 'events/', etc.
|
||||
build.onResolve({ filter: /^(process|string_decoder|events|buffer|stream|util|path)\/$/ }, (args) => {
|
||||
const builtin = args.path.replace(/\/$/, '');
|
||||
return { path: builtin, external: true };
|
||||
});
|
||||
},
|
||||
}],
|
||||
|
||||
// Don't minify - keep readable for debugging production issues
|
||||
minify: false,
|
||||
sourcemap: false,
|
||||
|
||||
// Tree-shake unused exports
|
||||
treeShaking: true,
|
||||
|
||||
// CJS interop banner: provide require(), __filename, __dirname for ESM bundle.
|
||||
// Express and other CJS dependencies need require() to work inside the ESM wrapper.
|
||||
banner: {
|
||||
js: [
|
||||
'// HOT-Step CPP Server - bundled build',
|
||||
'// Generated by release/esbuild.config.mjs',
|
||||
'',
|
||||
'// CJS interop: provide require() for ESM bundle',
|
||||
'import { createRequire as __bundleCreateRequire } from "module";',
|
||||
'const require = __bundleCreateRequire(import.meta.url);',
|
||||
'',
|
||||
].join('\n'),
|
||||
},
|
||||
|
||||
// Log build stats
|
||||
logLevel: 'info',
|
||||
metafile: true,
|
||||
});
|
||||
|
||||
// Print bundle size summary
|
||||
const outputs = result.metafile?.outputs || {};
|
||||
for (const [file, info] of Object.entries(outputs)) {
|
||||
const sizeKB = (info.bytes / 1024).toFixed(1);
|
||||
console.log(` ${file}: ${sizeKB} KB`);
|
||||
}
|
||||
|
||||
console.log('\n\u2705 Server bundle complete');
|
||||
Reference in New Issue
Block a user