@hyperfrontend/builder
Composable, vendor-neutral build toolkit for TypeScript libraries, JS bins, and Node SEA native binaries.
What is @hyperfrontend/builder?
@hyperfrontend/builder is a build-time Node.js toolkit that turns a TypeScript
source tree into a publishable npm package. From a single declarative config it
discovers entry points, resolves externals, bundles each entry in isolation,
emits type declarations, synthesizes the output package.json, copies assets,
and, optionally, produces JavaScript bins and standalone Node SEA native
binaries.
It is vendor-neutral: nothing about a consumer's workspace (package naming, which deps are first-party, hoist policy) is hard-coded. You inject those opinions through predicates and config, so the same toolkit drives a leaf utility library and a multi-entry framework alike.
Key Features
- Multi-format output: emit ESM, CJS, IIFE, and UMD bundles from one config; omit a format to skip it.
- Bins & native binaries: synthesize JavaScript bins and cross-platform Node SEA native executables.
- Per-entry isolation: each entry point bundles independently, keeping peak memory bounded on large graphs.
- Predicate-driven extensibility: classify workspace packages, externals, and assets with plain functions instead of config DSLs.
- Self-contained packages: bundle first-party and third-party dependencies, with an additive post-emit pass that dedups shared internals into
_shared/chunks. - Composable phases: run the bundle, package, and bin phases together via
build, or drive each phase on its own.
Architecture Highlights
buildorchestrates; phases compose.build(config)runs the full pipeline, whilerunBundlePhase,runPackagePhase, andrunBinPhaseremain individually callable against a sharedBuildContextfromcreateBuildContext.- Predicate extension model. Externals, workspace membership, and asset conditions are expressed as predicates (
byNames,byPrefix, or your own), keeping the core free of workspace-specific assumptions. - Memory-aware by design. Per-entry bundling plus an opt-in memory monitor (
createMemoryMonitor,recover) keep large builds inside constrained environments.
Why Use @hyperfrontend/builder?
Most library bundlers assume one entry point, one format, and a fixed notion of
what is "external." @hyperfrontend/builder is built for monorepos that publish
many packages with shared internals and varied output needs:
- You need ESM and CJS and CDN-ready bundles from the same source.
- You ship CLIs and want native binaries without standing up a separate SEA pipeline.
- You want bundled, self-contained packages without forcing transitive installs on consumers.
- You want to script the build programmatically (or hand it to the
hf-buildCLI) without adopting a heavyweight, opinionated framework.
Installation
npm install --save-dev @hyperfrontend/builder
typescript is a required peer dependency: the builder drives declaration emit
through your project's TypeScript and is built against TypeScript >= 5.9.
Install it alongside the builder if your project does not already depend on it:
npm install --save-dev "typescript@>=5.9"
Quick Start
Drive the full pipeline programmatically with build:
import { build, byPrefix } from '@hyperfrontend/builder'
const result = await build({
projectRoot: '/abs/path/to/libs/my-lib',
workspaceRoot: '/abs/path/to/workspace',
// Treat sibling workspace packages as first-party (bundled), everything else external.
isWorkspacePackage: byPrefix('@my-scope/'),
esm: { bundleWorkspaceDeps: true },
cjs: { bundleWorkspaceDeps: true },
})
console.log(result)
Or build straight from a JSON config with the bundled CLI:
# Reads ./builder.config.json by default
hf-build --config ./builder.config.json --verbose
Need finer control? Compose the phases yourself:
import { createBuildContext, runBundlePhase, runPackagePhase } from '@hyperfrontend/builder'
const ctx = createBuildContext(config)
await runBundlePhase(ctx, config)
await runPackagePhase(ctx, config, /* formats */ [])
API Overview
| Export | Description |
|---|---|
build | Run the full pipeline (bundle → package → bin) from a BuildConfig. |
createBuildContext | Derive the shared BuildContext used by the individual phases. |
runBundlePhase | Emit per-entry bundles and declarations for the configured formats. |
runPackagePhase | Synthesize the output package.json, assets, and license file. |
runBinPhase | Synthesize JavaScript bins and Node SEA native binaries. |
createMemoryMonitor / recover | Observe build memory pressure and recover from soft limits. |
byNames / byPrefix | Preset predicate factories for classifying packages and externals. |
Advanced primitives are available under sub-path entries: for example
@hyperfrontend/builder/presets, @hyperfrontend/builder/bundle,
@hyperfrontend/builder/package, and @hyperfrontend/builder/bin. See the
documentation for the
full surface.
Compatibility
@hyperfrontend/builder is a build-time tool that runs on Node.js. It is not
intended for browser, Web Worker, or CDN runtimes.
| Environment | Supported |
|---|---|
| Node.js >= 18 | ✅ |
| npm >= 8 | ✅ |
| TypeScript >= 5.9 | ✅ |
| Browser | ❌ |
License
API Reference§
Module Structure
21 modules · 246 total exports
@hyperfrontend/builder
Composable, vendor-neutral build toolkit for TypeScript libraries, JS bins, and Node SEA native binaries.
@hyperfrontend/builder/bin
JS bin synthesis, composed via runBinPhase.
@hyperfrontend/builder/bin/native
Node SEA native binary primitives: config generation, blob prep, host resolution, postject injection, and macOS code-sign cleanup.
@hyperfrontend/builder/bin/native/worker
Forked-worker entry script that runs a single postject inject via runInjectWorkerJob, isolating its ~138 MB buffer from the parent RSS.
@hyperfrontend/builder/bin/script
JS bin synthesis primitives: rollup-driven bundling with shebang + bootstrap footer + chmod.
@hyperfrontend/builder/bundle
Bundle phase orchestrator: entry discovery, externals, Rollup, and declaration emission, run in order via runBundlePhase.
@hyperfrontend/builder/bundle/declarations
tsc-driven `.d.ts` emission, path flattening, the bundled-dep d.ts pre-pass, per-entry inlining, sibling-subpath dedup, and the emitted-type-surface check.
@hyperfrontend/builder/bundle/dedupe
Additive post-emit pass that hoists first-party modules inlined into multiple per-entry bundles into shared chunks. See hoistSharedFirstParty.
@hyperfrontend/builder/bundle/dependencies
Per-format pre-pass and externalize plugin that bundle each third-party (and workspace) dep once, then reroute every entry's import to it.
@hyperfrontend/builder/bundle/dependencies/worker
Forked-worker entry script that runs a single dependency pre-pass via runPrePassWorkerJob.
@hyperfrontend/builder/bundle/entries
Entry-point discovery, resolution, and platform filtering primitives.
@hyperfrontend/builder/bundle/externals
Externals resolution primitives: package.json scanning and globals validation for IIFE / UMD bundles.
@hyperfrontend/builder/bundle/rollup
Rollup driver: per-format descriptor builders and the per-entry forked-worker dispatcher.
@hyperfrontend/builder/bundle/rollup/worker
Forked-worker entry script that runs a single per-entry rollup pass via runRollupWorkerJob.
@hyperfrontend/builder/memory
Opt-in memory monitor and the always-on `recover()` event-loop yield.
@hyperfrontend/builder/models
Type definitions for builder configuration, context, and results.
@hyperfrontend/builder/package
Package phase: package.json synthesis, asset copy, and license collection composed via runPackagePhase.
@hyperfrontend/builder/package/assets
Generic, data-driven asset-copy primitive consumed by the package phase. See copyAssets.
@hyperfrontend/builder/package/json
package.json synthesis primitives: read, inherit, filter, generate exports/CDN paths, and write the dist manifest.
@hyperfrontend/builder/package/licenses
Opt-in third-party license collection that writes `THIRD_PARTY_LICENSES.md` to the dist root.
@hyperfrontend/builder/presets
Predicate factories for the IsWorkspacePackagePredicate slot on BuildConfig, opting a build into workspace-aware behavior.