Skip to content

research: can bun zero-install get lockfile-like reproducible versions? #705

Description

@vivek7405

Question

Can bun zero-install (no node_modules, no bun install) get lockfile-like reproducible versions? Specifically: if we generate a bun.lock fast via bun install --lockfile-only and commit it, does bun's RUNTIME auto-install honor that lock and resolve BARE imports to the locked versions? If yes, the entire webjs pin shim (#685/#698/#699/#700/#703/#704/#709) could be deleted and the scaffold would just commit a bun.lock.

Verdict (bun 1.3.14): NO

A committed bun.lock does NOT make bun's runtime auto-install resolve bare imports. The pin shim stays. bun.lock is not a viable replacement for the zero-install default.

Empirically:

  • bun install --lockfile-only works as advertised: generates bun.lock in ~220ms, writes NO node_modules. So the FAST lock generation half of the other-agent claim is TRUE.
  • But the RUNTIME half is FALSE. With bun.lock pinning lodash@4.17.20, that version cached, and NO node_modules, a bare import('lodash') ENOENTs (error: ENOENT while resolving package 'lodash'), identically with or without the lock, via both bun run x.mjs and bun x.mjs. The lock is simply not consulted for bare-import resolution.
  • Positive control: in the SAME dir, an INLINE import('lodash@4.17.20') resolves to 4.17.20 from cache. So the cache is fine and inline specifiers resolve reliably. Inline is exactly what the pin shim produces.
  • Bare imports are also inconsistent (a cached cowsay@1.6.0, which is also latest, loaded bare; lodash@4.17.20 with latest 4.17.21 did not), matching bun's own source comment that auto-install "always installs the latest version regardless of package.json". When a bare import resolves at all it targets latest, never the locked/declared version when they differ.

Implication

  1. The bun.lock path cannot delete the pin shim. The shim (rewrite bare specifier to inline-versioned) is the ONLY reliable mechanism, because inline specifiers resolve where bare ones ENOENT. This REINFORCES docs: make the bun auto-install pin shim self-documenting + deletable #714 (document the shim) and harden the bun auto-install pin shim (fail-open, capability probe, escape hatch, CI canary) #715 (harden it).
  2. bun.lock as an opt-in reproducibility tier is ALSO not useful today: bun's runtime ignores it for bare resolution, so committing it buys nothing at runtime on 1.3.14. (It may help editor tooling or a future bun.)
  3. The capability probe in harden the bun auto-install pin shim (fail-open, capability probe, escape hatch, CI canary) #715 is the right ongoing mechanism: if a future bun honors the lock or package.json for bare imports, the probe detects it and the shim self-disables. CI-against-canary (harden the bun auto-install pin shim (fail-open, capability probe, escape hatch, CI canary) #715) is how we learn when that day arrives. This research should be re-run on each major bun release.

Verified on bun 1.3.14. Re-test on canary / future releases via the #715 CI-canary job.

Metadata

Metadata

Assignees

Labels

researchResearch/design/decision record (no code); filter these to read design history

Type

No type
No fields configured for issues without a type.

Projects

Status
Done

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions