Other bundlers
Heximon's compile step is a build-time concern: walk the modules, build the DI graph, emit plain JS wiring
into .heximon/. That work isn't tied to any one bundler — so @heximon/build
exposes it as an unplugin factory with a per-bundler entry point. Your src/
never changes; you pick the bundler.
The @heximon/build/vite entry is the complete Vite plugin: the build-error page, the JSON-preview page,
recompile-on-change, browser auto-reload, and dev WebSocket-upgrade handling — a ws:// route connects under
pnpm dev.
The Rollup, Rolldown, esbuild, webpack, and rspack entries are build tiers: they run the compiler and let the bundler emit a runnable server bundle, with diagnostics to the terminal.
The live dev server is
Vite-only — webpack and rspack have no way to run the compiled app in-process, so they compile and build but
do not host the running app (use @heximon/build/vite, or the Nitro dev plugin, for that).
Which path should you use?
Most Heximon apps never hand-write a bundler config. Develop with @heximon/build/vite (pnpm dev — the
full dev experience above) and deploy with Nitro, which owns the production build and
targets Node, Workers, Deno, Bun, and Lambda from one codebase. Both are owned-build hosts: you add one
plugin/module and never touch resolve, externals, or loaders — the same way SvelteKit or Nuxt hide their bundler.
Reach for the per-bundler build entries (/rollup, /rolldown, /esbuild, /webpack, /rspack) when
you're folding Heximon into a project that already builds with one of those bundlers — a monorepo
standardized on webpack, say.
On that path you write that bundler's ordinary config (entry, output, externals,
and its standard .js→.ts TypeScript handling — resolve.extensionAlias on webpack/rspack, a resolve plugin
on esbuild/rollup, nothing on Rolldown), exactly as any TypeScript-ESM project on that bundler already does.
The gap's alternate-bundlers example shows a complete, runnable config per bundler.
Install
pnpm add -D @heximon/build
npm install -D @heximon/build
yarn add -D @heximon/build
bun add -d @heximon/build
vite, rollup, rolldown, and esbuild are optional peer dependencies — install whichever bundler you
actually use; the matching @heximon/build/<bundler> entry pulls in nothing else. webpack and rspack work
the same way but are not declared as peers (their entries are typed structurally and import neither package) —
install the bundler yourself.
Develop on Vite
@heximon/build/vite is a drop-in for the dev server. The plugin takes no arguments — Heximon config lives in
heximon.config.ts, the same file createTestApp reads:
import heximon from "@heximon/build/vite";
import { defineConfig } from "vite-plus";
export default defineConfig({
plugins: [heximon()],
server: { port: 3002 },
});
import { defineHeximonConfig } from "@heximon/build";
import { HttpPlugin } from "@heximon/http/compiler";
export default defineHeximonConfig({ plugins: [new HttpPlugin()] });
On pnpm dev you get the full surface: a source edit recompiles src/ and reloads the browser; a broken
compile shows the diagnostic codeframe in the browser (and a real 500 to curl / a JSON client) instead
of a stale response; a browser navigation to a JSON route renders the syntax-highlighted preview page; and a
WebSocket route upgrades its ws:// connection automatically.
Build on Rollup, Rolldown, esbuild, webpack, or rspack
The build entries compile src/ to .heximon/ on buildStart (reporting compile diagnostics to the
terminal); the bundler then bundles the generated server.js entry — and the src/ it imports — into your
output. Framework packages (@heximon/*) are left external for the runtime to resolve. Each factory takes no
arguments — compiler plugins are read from heximon.config.ts:
import heximon from "@heximon/build/rolldown";
import { fileURLToPath } from "node:url";
import { isAbsolute } from "node:path";
import { defineConfig } from "rolldown";
export default defineConfig({
input: fileURLToPath(new URL(".heximon/server.js", import.meta.url)),
plugins: [heximon()],
resolve: {
extensionAlias: { ".js": [".ts", ".js"] },
conditionNames: ["import", "default"],
},
external: (id) => !id.startsWith(".") && !isAbsolute(id),
output: { dir: "dist", format: "esm" },
});
The generated entry re-exports the web fetch handler and the disposable app, so the bundle is a runnable
server (dist/server.js exporting { app, fetch }).
The Rollup, esbuild, webpack, and rspack configs follow the
same shape via @heximon/build/rollup, @heximon/build/esbuild, @heximon/build/webpack, and
@heximon/build/rspack.
Rolldown and esbuild transpile the app's .ts sources out of the box; Rollup, webpack,
and rspack need a TypeScript loader of your choosing (e.g. webpack/rspack's builtin:swc-loader) so the bundler
can read the src/ the generated wiring imports.
Package as a library
The same cross-bundler reach applies to library mode — packaging a Heximon module so another app can consume it.
@heximon/library is the bundler-agnostic library emit (separate from
@heximon/build): it compiles in library mode, writes the typed create<Module>.ts factory + a
src/.heximon/library/index.ts barrel, and emits dist/heximon.manifest.json.
It is exposed per bundler as a
default-export factory — @heximon/library/vite, @heximon/library/rollup, @heximon/library/rolldown,
@heximon/library/esbuild.
Under vp pack (Rolldown/tsdown) the factory ships on the package's dedicated
./heximon subpath, fully wired by the plugin. On the other bundlers you add the generated barrel
(src/.heximon/library/index.ts) as a second entry and the ./heximon export-map entry yourself — the emit
detects the committed entry and shapes the manifest to match:
// build.mjs (packaging a module with esbuild)
import heximonLibrary from "@heximon/library/esbuild";
import { build } from "esbuild";
await build({
entryPoints: ["src/index.ts"],
bundle: true,
format: "esm",
outdir: "dist",
external: ["@heximon/*"], // the framework stays a single cross-boundary copy
plugins: [heximonLibrary()], // compiler plugins are read from heximon.config.ts
});
Whichever bundler you package with, the published factory and manifest are identical. See the
library mode guide for the boundary module, the peerDependencies rule, and how
a host consumes the package.
Capability matrix
The dev experience needs a dev server, which only Vite exposes through unplugin. Every entry compiles and serves the generated wiring; the tiers differ in what the bundler offers on top.
| Entry | Compile + wiring | Recompile on change | Dev server (error page · JSON preview · auto-reload · ws:// upgrade) | Tier |
|---|---|---|---|---|
@heximon/build/vite | ✅ in-memory | ✅ | ✅ full (incl. WebSocket-in-dev) | Full dev |
@heximon/build/rollup | ✅ to disk | ✅ (watch) | ❌ terminal diagnostics | Build |
@heximon/build/rolldown | ✅ to disk | ✅ (watch) | ❌ terminal diagnostics | Build |
@heximon/build/esbuild | ✅ to disk | ❌ (no watch hook) | ❌ terminal diagnostics | Build |
@heximon/build/webpack | ✅ to disk | ✅ (per rebuild) | ❌ terminal diagnostics | Build |
@heximon/build/rspack | ✅ to disk | ✅ (per rebuild) | ❌ terminal diagnostics | Build |
Only Vite exposes a dev server through unplugin, and only Vite can run the compiled app in-process — so webpack
and rspack are build targets only (compile + diagnostics + a runnable bundle), with no live dev server. Use
rspack ≥ 1.5.0 (older versions write placeholder virtual-module files that collide with the .heximon/ write).
How it shares the dev experience
@heximon/build is a thin adapter over the same engine the Vite and Nitro hosts use. The
build-time-only @heximon/dev package owns the compile / serve-last-good / recompile core
(DevServerCore) behind a small DevHost adapter, plus the shared Vite host kit (ViteDevClient,
ViteDevHost, attachViteDevServer) at its ./vite subpath.
The @heximon/build/vite entry binds that kit to
Vite's dev server, so the build-error page, JSON preview, and auto-reload are the same code the Nitro host
runs — not a reimplementation. The /vite entry adds the WebSocket upgrade handler on top.
See also
- Hosts overview — every host that serves the compiled app, and how to pick one.
- Installation — set up the
@heximon/build/vitedev server this page builds on. - Packages —
@heximon/buildand@heximon/devin the package stack. - Cross-bundler build — the same app served by
pnpm dev(Vite) and built to a runnable bundle by all five build entries (build:rolldown/build:esbuild/build:rollup/build:webpack/build:rspack, orbuild:all).
Library Mode
Ship a Heximon module as a precompiled npm package — heximonLibrary(), the typed create<Module> factory, heximon.manifest.json, requires/exports boundary tokens, and peerDependencies.
Packages
All 44 @heximon/* packages by tier — foundation, kernel, architecture, data, api, capabilities, platforms, tooling — with the npm-name-to-directory mapping.