Getting started

netpack is a single native binary, distributed through npm. There’s no runtime to install and nothing to warm up — the CLI starts and behaves the same whether it’s bundling a two-file script or a large app.

Install

npm i -D netpack

This pulls in the wrapper package (netpack) plus the platform package for your OS/architecture (@netpack/linux-x64, @netpack/osx-arm64 or @netpack/win-x64). The wrapper just forwards to the native binary.

Entry points

netpack takes a single entry point and follows whatever it imports/references from there — same convention as Vite or Parcel:

  • an HTML file (index.html) — script/link/img/etc. references are resolved, bundled and rewritten in place;
  • a JavaScript/TypeScript file (main.mjs, app.tsx, …) — bundled directly, no HTML wrapper required;
  • a file literally named federation.json — treated specially, see Module Federation.

You don’t need a build config. If your project needs externals, shared dependencies, or has a tsconfig.json with JSX options, netpack picks that up automatically (see the other docs in this folder).

How a build flows

Whatever the entry, the shape of a build is the same: netpack parses the entry, follows what it references to build a module graph, groups that graph into chunks (pulling shared code into its own chunk), and renders each chunk to disk.

The netpack build pipeline A single entry point is parsed into a module graph, grouped into chunks, and emitted to the output directory. Entry html · js · ts Parse native, no Babel Graph resolve imports Chunks shared splitting Emit minify · maps One entry point becomes a module graph, then chunks, then files in dist/ — tree-shaking runs over the graph before emit.

Commands

bundle — one-shot production build

npx netpack bundle src/index.html
OptionDefaultMeaning
--outdir <dir>distWhere to write the output.
--minifyoffMinify the emitted JS/CSS/HTML.
--sourcemapoffEmit a .js.map next to each JS bundle.
--cleanoffDelete --outdir before writing.
--banner <text>Text placed on top of the entry JS bundle, followed by a newline. Empty banners are discarded. See Banner.
--licenses <mode>skipThird-party license handling: skip, preamble, json, or spdx. See Licenses.
--external <name>Repeatable. Don’t bundle this import; leave it as a real import for the browser/import map to resolve.
--shared <name>Repeatable. Like --external, but also builds the dependency as its own output chunk and wires it into an import map. See Import maps & externals.

serve — dev server with reload/HMR

npx netpack serve src/index.html

Watches the filesystem, recompiles on change, and pushes updates to the browser over a small SSE-based client:

  • if only module bodies changed, it sends a granular update and hot-swaps the affected module factories in place (no full reload);
  • if a module was added/removed, or something non-JS changed, it falls back to a full page reload.

Accepts --port (default 1234), plus --minify, --external, --shared and --banner from bundle. Source maps are always on in dev.

When the react-refresh package is resolvable from your project, the dev server automatically enables React Fast Refresh instead of plain HMR for component modules — see React & JSX.

analyze — inspect the bundle graph

npx netpack analyze src/index.html

Compiles (optimized) and reports on the resulting bundles: what’s in them, how big they are, how many modules each one pulls in.

It also audits the dependencies that made it into the graph against known vulnerabilities (npm advisories / CVEs) and includes the findings under an audit key in the metadata JSON — one entry per raised advisory (package, version, severity, CVSS score, CWE, advisory URL) plus a per-severity summary. Only the packages actually present in the graph are checked (tree-shaken ones are not), and a failed audit (offline, timeout) is recorded on the report rather than failing the run.

OptionMeaning
--outfile <file>Write the metadata as JSON instead of printing it.
--interactiveStart a small local server (default port 8080) with a visual explorer of the bundle graph, and keep recompiling on change.
--auditAudit dependencies for known vulnerabilities (default on; --audit false to disable).
--external, --sharedSame meaning as in bundle.

graph / inspect

Lower-level commands for printing the raw dependency graph or inspecting a single resolved module — mainly useful when debugging netpack itself or a tricky resolution issue.

You can also drive all of these from a Node.js program — see Programmatic use.

Output

For an HTML entry point, netpack writes:

  • the HTML file itself, with <script>/<link>/etc. src/href attributes rewritten to point at the emitted bundle files;
  • one JS bundle per connected component of the module graph (so code that’s never reached from more than one entry gets its own chunk automatically);
  • one CSS bundle when styles are imported from JS, or referenced directly from HTML;
  • anything placed in a public/ folder next to the entry file, copied as-is next to the output.

bundle prints a summary table of every emitted file, its size, and (for JS/CSS bundles) how many modules went into it.

Metafile JSON

Use analyze --outfile <path> to emit a machine-readable build manifest (esbuild format) in JSON. The metafile is useful for CI tooling, post-processing scripts, and visualizers.

npx netpack analyze src/index.html --outfile meta.json

Schema

The metafile has two top-level keys: inputs and outputs.

Inputs

Each key is a source file path (relative to the project root), mapping to:

FieldTypeDescription
bytesintSize of the raw source file in bytes
formatstringModule format ("esm")
importsarrayDependency edges — each with path (resolved file), kind ("import-statement", "require-call", "dynamic-import"), and original (the specifier as written)

Outputs

Each key is an emitted output file name, mapping to:

FieldTypeDescription
bytesintSize of the emitted file in bytes
entryPointstring?The output file name when this is the entry bundle, null for shared chunks and assets
flagsstring?"entry" for entry bundles, "shared" for split/shared chunks, null for assets
inputsobjectSource files bundled into this output. Each key is a relative path mapping to { "bytesInOutput": int }
exportsarrayExported names from this output (each with path and kind)
importsarrayBundles this output imports (each with path and kind)

Example

For a project with app.js importing helper.js:

npx netpack analyze app.js --outfile meta.json
{
  "inputs": {
    "app.js": {
      "bytes": 34,
      "format": "esm",
      "imports": [{ "path": "helper.js", "kind": "import-statement", "original": "./helper.js" }]
    },
    "helper.js": {
      "bytes": 38,
      "format": "esm",
      "imports": []
    }
  },
  "outputs": {
    "app.js": {
      "bytes": 412,
      "entryPoint": "app.js",
      "flags": "entry",
      "inputs": {
        "app.js": { "bytesInOutput": 184 },
        "helper.js": { "bytesInOutput": 228 }
      },
      "exports": [],
      "imports": []
    }
  }
}

Shared CSS chunks appear as non-entry outputs:

{
  "outputs": {
    "common.0001.css": {
      "bytes": 42,
      "entryPoint": null,
      "flags": "shared",
      "inputs": { "shared.css": { "bytesInOutput": 42 } },
      "exports": [],
      "imports": []
    }
  }
}