esdev build

Shell
esdev build server.ts                          # → dist/server.js
esdev build src/app.ts --out=dist/app.js --minify
esdev build styles/app.css --minify            # → dist/app.css

One entry, one file, ES modules out. runtime:* imports are left for the runtime to serve, and CommonJS dependencies are converted on the way in.

For a stylesheet entry, the output is CSS rather than JavaScript: its default is dist/<entry>.css. It follows local @imports before it writes. See Browser builds for CSS entry, asset, CSS Module, and library usage.

The CommonJS answer

esrun runs ES modules only, while a large share of npm still ships CommonJS. The bundler converts CJS to ESM on the developer's machine so the deployed artifact remains the text that was reviewed:

Shell
esdev build server.js         # a CJS dependency goes in
esrun dist/server.js          # ordinary ESM comes out

esdev test and esdev <file> convert a CommonJS package as they load it, so a test needs no build step. See Imports.

A shorter deploy line

An unbundled program needs --allow-imports, because the loader walks node_modules at runtime. A bundle has no imports left to resolve:

Shell
esrun --allow-imports --allow-listen=8080 app.js  # unbundled
esrun --allow-listen=8080 dist/app.js             # bundled

The build is a security step, not only a packaging one.

Options

Flag
--out=<file>Where to write it (default dist/<entry>.js, or dist/<entry>.css for a stylesheet)
--minifyMinify the output
--conditions=<list>Extra exports conditions, comma-separated; these add to import, default, worker
--define=<name>=<value>Replace a name at build time; process.env.NODE_ENV defaults to "production"
--alias=<name>=<to>Rewrite a specifier before it resolves; repeatable
--sourcemap[=<kind>]A .map beside the output, or =inline, or =hidden
--target=<name>Build one target of the project's esdev.json
--config=<path>Read this project file instead of ./esdev.json
--lib, --format, --no-types, --dts-bundle, --css-urlsA library build (Library builds)

esdev build with no entry builds the targets esdev.json describes, each flag applied to every one of them (Flags on a project build). Naming an entry builds that one, with the project's jsx, resolve.alias and plugins.

What the application build guarantees

runtime:* stays externalIt is served by the runtime and has no file behind it.
ESM outputThe runtime has no other module system.
process.env.NODE_ENV is definedPackages branch on it before doing anything, and there is no ambient process global.
The worker condition is assertedPackages can select their Web-API build.

--conditions adds rather than replaces, so asking for one more cannot silently cost the worker condition. A dynamic import() emits a content-hashed chunk beside the entry.

A module named with new URL("./path.js", import.meta.url) is built as a content-hashed chunk of its own, and the URL is rewritten to point at it. That is how a Worker finds its entry in the output, and how a durable worker's shards find the module that defines their classes:

JavaScript
new Worker(new URL("./resize.worker.ts", import.meta.url));
configure({ shards: "auto", module: new URL("./workers.js", import.meta.url) });

Only a literal path to a JavaScript or TypeScript module, with import.meta.url as the base, is built this way. A literal path to any other file is copied into the output, and a computed path is left as written.

The bundler's warnings are printed as the build runs. The one to act on is an import it could not resolve: the bundle keeps it as an import and the build succeeds, but the program fails where it is deployed, so the warning names the file and the line.

Source maps

Shell
esdev build src/server.ts --out=dist/server.js --sourcemap

Source maps are off unless asked. The available forms are:

OptionResult
--sourcemapA .map beside the output, pointed at by the bundle
--sourcemap=inlineA data URL in the file itself
--sourcemap=hiddenWritten, with nothing pointing at it — useful for an error reporter
"sourcemap": trueThe same setting per target in esdev.json; "inline", "hidden" and false are also supported

A map's sources are relative to the map, so a deployment can be copied anywhere with its sources and still resolve them. The map names nothing about the machine that built it.

esrun remaps printed stack traces through the map, while error.stack inside the program remains the engine's original value.

Not yet

Watching a build, and ?raw / ?url suffixes on an import.

Choose a focused guide

  • Project builds — esdev.json, multiple targets, aliases, environment values, plugins and safe output replacement.

  • Browser builds — HTML entries, imported assets, stylesheets and CSS Modules.

  • Library builds — --lib, declarations and CommonJS output.

Last updated on
Edit this page