| title | description |
|---|---|
Auto-install |
Bun's automatic package installation feature for standalone script execution |
If no node_modules directory is found in the working directory or higher, Bun will abandon Node.js-style module resolution in favor of the Bun module resolution algorithm.
Under Bun-style module resolution, all imported packages are auto-installed on the fly into a global module cache during execution (the same cache used by bun install).
import { foo } from "foo"; // install `latest` version
foo();The first time you run this script, Bun will auto-install "foo" and cache it. The next time you run the script, it will use the cached version.
To determine which version to install, Bun follows the following algorithm:
- Check for a
bun.lockfile in the project root. If it exists, use the version specified in the lockfile. - Otherwise, scan up the tree for a
package.jsonthat includes"foo"as a dependency. If found, use the specified semver version or version range. - Otherwise, use
latest.
Once a version or version range has been determined, Bun will:
- Check the module cache for a compatible version. If one exists, use it.
- When resolving
latest, Bun will check ifpackage@latesthas been downloaded and cached in the last 24 hours. If so, use it. - Otherwise, download and install the appropriate version from the
npmregistry.
Packages are installed and cached into <cache>/<pkg>@<version>, so multiple versions of the same package can be cached at once. Additionally, a symlink is created under <cache>/<pkg>/<version> to make it faster to look up all versions of a package that exist in the cache.
This entire resolution algorithm can be short-circuited by specifying a version or version range directly in your import statement.
import { z } from "zod@3.0.0"; // specific version
import { z } from "zod@next"; // npm tag
import { z } from "zod@^3.20.0"; // semver rangeThis auto-installation approach is useful for a few reasons:
- Space efficiency — Each version of a dependency only exists in one place on disk. This is a huge space and time savings compared to redundant per-project installations.
- Portability — To share simple scripts and gists, your source file is self-contained. No need to
ziptogether a directory containing your code and config files. With version specifiers inimportstatements, even apackage.jsonisn't necessary. - Convenience — There's no need to run
npm installorbun installbefore running a file or script. Justbun runit. - Backwards compatibility — Because Bun still respects the versions specified in
package.jsonif one exists, you can switch to Bun-style resolution with a single command:rm -rf node_modules.
- No Intellisense. TypeScript auto-completion in IDEs relies on the existence of type declaration files inside
node_modules. We are investigating various solutions to this. - No patch-package support
<Accordion title="How is this different from what pnpm does?">
With pnpm, you have to run `pnpm install`, which creates a `node_modules` folder of symlinks for the runtime to resolve. By contrast, Bun resolves dependencies on the fly when you run a file; there's no need to run any `install` command ahead of time. Bun also doesn't create a `node_modules` folder.
</Accordion>
<Accordion title="How is this different from Yarn Plug'N'Play does?">
With Yarn, you must run `yarn install` before you run a script. By contrast, Bun resolves dependencies on the fly when you run a file; there's no need to run any `install` command ahead of time.
Yarn Plug'N'Play also uses zip files to store dependencies. This makes dependency loading [slower at runtime](https://twitter.com/jarredsumner/status/1458207919636287490), as random access reads on zip files tend to be slower than the equivalent disk lookup.
</Accordion>
<Accordion title="How is this different from what Deno does?">
Deno requires an `npm:` specifier before each npm `import`, lacks support for import maps via `compilerOptions.paths` in `tsconfig.json`, and has incomplete support for `package.json` settings. Unlike Deno, Bun does not currently support URL imports.
</Accordion>