Skip to Content
Examples08 · Bundler

08 · Bundler

Two modules (index.js imports formatTime from utils.js) bundled into a single file that runs on its own under 3va or in a browser.

Source: examples/08-bundler

Build and run

cd examples/08-bundler 3va bundle src/index.js -o dist/bundle.js --minify
✓ Bundle created: dist/bundle.js Run: 3va run dist/bundle.js --allow-net=<trusted-hosts>
3va run dist/bundle.js
{"greeting":"Hello, 3va!","timestamp":"17:19:20","generatedBy":"3va bundler"}

The hint about --allow-net is generic. This bundle needs no permissions.

How it works

The bundler follows the real import graph (project files and node_modules, ESM and CommonJS), converts every module to a CommonJS-style function, and wraps them in one IIFE with a tiny module registry:

dist/bundle.js (unminified, abridged)
(function() { var __modules = { "./src/utils.js": function(module, exports, require) { function formatTime(date) { … } module.exports.formatTime = formatTime; }, "./src/index.js": function(module, exports, require) { var { formatTime } = require("./src/utils.js"); … }, }; … })();

.json imports are inlined, and .css imports become a <style> tag injected at runtime in the browser.

The entry decides where it’s running:

src/index.js
if (typeof window === "undefined") { console.log(createMessage("3va")); // 3va run } else { globalThis.createMessage = createMessage; // browser <script> }

public/index.html loads /bundle.js with a classic <script> and then calls createMessage("browser").

Things to keep in mind

  • Module IDs are relative to the directory you run 3va bundle from. From the example folder they are ./src/utils.js. From src/ they would be ./utils.js. No absolute paths from your machine end up in the bundle.

  • --minify removes whitespace but doesn’t rename. In this example the output only went from 1453 to 1266 bytes. Function and variable names were kept as-is. Use a dedicated minifier afterwards if size is critical.

  • --source-map and --split aren’t supported yet. They appear in 3va bundle --help, but using either one stops the command with exit code 1 and writes nothing:

    Error: --source-map is not supported yet by `3va bundle`; run it without that flag
  • The output is a classic script, not an ES module. Exports aren’t visible to the page. Expose what the page needs on globalThis, as the example does.

  • A bundle runs with the same permissions as any script. Bundling doesn’t grant anything. If the code reads files or opens sockets, 3va run dist/bundle.js still needs the matching --allow-* flags. One upside: since everything is inlined, you no longer need --allow-read for your own modules or node_modules.

  • There’s no watch mode on 3va bundle. For automatic rebuilds, run 3va dev, which also writes dist/bundle.js.