aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md305
1 files changed, 173 insertions, 132 deletions
diff --git a/README.md b/README.md
index 058112764..3141e57f4 100644
--- a/README.md
+++ b/README.md
@@ -11,11 +11,45 @@ Bun is a new:
All in one fast & easy-to-use tool. Instead of 1,000 node_modules for development, you only need Bun.
-**Bun is experimental software**. Join [Bun's Discord](https://bun.sh/discord) for help and have a look at [things that don't work yet](#things-that-dont-work-yet).
-
-## Install:
-
-```
+**Bun is experimental software**. Join [Bun’s Discord](https://bun.sh/discord) for help and have a look at [things that don’t work yet](#things-that-dont-work-yet).
+
+## Table of Contents
+
+- [Install](#install)
+- [Benchmarks](#benchmarks)
+- [Using Bun as a package manager](#using-bun-as-a-package-manager)
+- [Using Bun as a task runner](#using-bun-as-a-task-runner)
+- [Using Bun with Next.js](#using-bun-with-nextjs)
+- [Using Bun with single page apps](#using-bun-with-single-page-apps)
+ - [Using Bun with Create React App](#using-bun-with-create-react-app)
+- [Using Bun with TypeScript](#using-bun-with-typescript)
+- [Using Tailwind with Bun](#using-tailwind-with-bun)
+- [Things that don’t work yet](#things-that-dont-work-yet)
+ - [Limitations & intended usage](#limitations--intended-usage)
+- [Configuration](#configuration)
+ - [Loaders](#loaders)
+ - [CSS in JS](#css-in-js)
+ - [CSS Loader](#css-loader)
+ - [CSS Runtime](#css-runtime)
+ - [Frameworks](#frameworks)
+- [Troubleshooting](#troubleshooting)
+- [Reference](#reference)
+ - [`bun install`](#bun-install)
+ - [`bun run`](#bun-run)
+ - [`bun create`](#bun-run)
+ - [`bun bun`](#bun-bun)
+ - [`bun completions`](#bun-completions)
+- [Environment variables](#environment-variables)
+- [Credits](#credits)
+- [License](#license)
+- [Developing Bun](#developing-bun)
+ - [MacOS](#macos)
+ - [Linux](#linux)
+- [vscode-zig](#vscode-zig)
+
+## Install
+
+```sh
curl -fsSL https://bun.sh/install | bash
```
@@ -27,9 +61,9 @@ curl -fsSL https://bun.sh/install | bash
## Using Bun as a package manager
-On Linux, `bun install` tends to install packages 20x - 100x faster than `npm install`. On macOS, it's more like 4x - 80x.
+On Linux, `bun install` tends to install packages 20x - 100x faster than `npm install`. On macOS, it’s more like 4x - 80x.
-<img src="https://user-images.githubusercontent.com/709451/147004342-571b6123-17a9-49a2-8bfd-dcfc5204047e.png" height=200 />
+<img src="https://user-images.githubusercontent.com/709451/147004342-571b6123-17a9-49a2-8bfd-dcfc5204047e.png" height="200" />
To install packages from package.json:
@@ -87,9 +121,9 @@ bun bun --use next
bun
```
-Many of Next.js' features are supported, but not all.
+Many of Next.js’ features are supported, but not all.
-Here's what doesn't work yet:
+Here’s what doesn’t work yet:
- `getStaticPaths`
- same-origin `fetch` inside of `getStaticProps` or `getServerSideProps`
@@ -114,7 +148,7 @@ bun
By default, `bun` will look for any HTML files in the `public` directory and serve that. For browsers navigating to the page, the `.html` file extension is optional in the URL, and `index.html` will automatically rewrite for the directory.
-Here are examples of routing from `public/` and how they're matched:
+Here are examples of routing from `public/` and how they’re matched:
| Dev Server URL | File Path |
|----------------|-----------|
| /dir | public/dir/index.html |
@@ -127,7 +161,7 @@ Here are examples of routing from `public/` and how they're matched:
If `public/index.html` exists, it becomes the default page instead of a 404 page, unless that pathname has a file extension.
-#### Using Bun with Create React App
+### Using Bun with Create React App
To create new a React app:
@@ -164,19 +198,19 @@ You do not need to include file extensions in `import` paths. CommonJS-style imp
You can override the public directory by passing `--public-dir="path-to-folder"`.
-If no directory is specified and `./public/` doesn't exist, Bun will try `./static/`. If `./static/` does not exist, but won't serve from a public directory. If you pass `--public-dir=./` Bun will serve from the current directory, but it will check the current directory last instead of first.
+If no directory is specified and `./public/` doesn’t exist, Bun will try `./static/`. If `./static/` does not exist, but won’t serve from a public directory. If you pass `--public-dir=./` Bun will serve from the current directory, but it will check the current directory last instead of first.
## Using Bun with TypeScript
-TypeScript just works. There's nothing to configure and nothing extra to install. If you import a `.ts` or `.tsx` file, Bun will transpile it into JavaScript. Bun also transpiles `node_modules` containing `.ts` or `.tsx` files. This is powered by Bun's TypeScript transpiler, so it's fast.
+TypeScript just works. There’s nothing to configure and nothing extra to install. If you import a `.ts` or `.tsx` file, Bun will transpile it into JavaScript. Bun also transpiles `node_modules` containing `.ts` or `.tsx` files. This is powered by Bun’s TypeScript transpiler, so it’s fast.
Bun also reads `tsconfig.json`, including `baseUrl` and `paths`.
## Using Tailwind with Bun
-[Tailwind](https://tailwindcss.com/) is a popular CSS utility framework. Currently, the easiest way to use Tailwind with Bun is through Tailwind's CLI. That means running both `bun` and `tailwind`, and importing the file `tailwind`'s CLI outputs.
+[Tailwind](https://tailwindcss.com/) is a popular CSS utility framework. Currently, the easiest way to use Tailwind with Bun is through Tailwind’s CLI. That means running both `bun` and `tailwind`, and importing the file `tailwind`’s CLI outputs.
-Tailwind's docs talk more about [Tailwind's CLI usage](https://tailwindcss.com/docs/installation#watching-for-changes), but the gist is you'll want to run this:
+Tailwind’s docs talk more about [Tailwind’s CLI usage](https://tailwindcss.com/docs/installation#watching-for-changes), but the gist is you’ll want to run this:
```bash
npx tailwindcss -i ./src/tailwind.css -o ./dist/tailwind.css --watch
@@ -184,9 +218,9 @@ npx tailwindcss -i ./src/tailwind.css -o ./dist/tailwind.css --watch
From there, make sure to import the `dist/tailwind.css` file (or what you chose as the output).
-## Things that don't work yet
+## Things that don’t work yet
-Bun is a project with incredibly large scope, and it's early days.
+Bun is a project with incredibly large scope, and it’s early days.
| Feature | In |
| ---------------------------------------------------------------------------------------------------------------------- | --------------- |
@@ -210,25 +244,30 @@ Bun is a project with incredibly large scope, and it's early days.
| [link: dependencies](https://github.com/Jarred-Sumner/bun/issues/81) | Package manager |
| [global installs](https://github.com/Jarred-Sumner/bun/issues/84) | Package manager |
-<sup>JS Transpiler == JavaScript Transpiler</sup><br/>
-<sup>TS Transpiler == TypeScript Transpiler</sup><br/>
-<sup>Package manager == `bun install`</sup><br/>
-<sup>Bun.js == Bun's JavaScriptCore integration that executes JavaScript. Similar to how Node.js & Deno embed V8.</sup><br/>
+<small>
+JS Transpiler == JavaScript Transpiler
+<br/>
+TS Transpiler == TypeScript Transpiler
+<br/>
+Package manager == `bun install`
+<br/>
+Bun.js == Bun’s JavaScriptCore integration that executes JavaScript. Similar to how Node.js & Deno embed V8.
+</small>
### Limitations & intended usage
-Bun is great for building websites &amp; webapps. For libraries, consider using Rollup or esbuild instead. Bun currently doesn't minify code and Bun's dead code elimination doesn't look beyond the current file.
+Bun is great for building websites &amp; webapps. For libraries, consider using Rollup or esbuild instead. Bun currently doesn’t minify code and Bun’s dead code elimination doesn’t look beyond the current file.
Today, Bun is focused on:
- Development, not production
- Compatibility with existing frameworks & tooling
-Ideally, most projects can use Bun with their existing tooling while making few changes to their codebase. That means using Bun in development, and continuing to use Webpack, esbuild, or another bundler in production. Using two bundlers might sound strange at first, but after all the production-only AST transforms, minification, and special development/production-only imported files...it's not far from the status quo.
+Ideally, most projects can use Bun with their existing tooling while making few changes to their codebase. That means using Bun in development, and continuing to use Webpack, esbuild, or another bundler in production. Using two bundlers might sound strange at first, but after all the production-only AST transforms, minification, and special development/production-only imported files...it’s not far from the status quo.
Longer-term, Bun intends to replace Node.js, Webpack, Babel, and PostCSS (in production).
-# Configuration
+## Configuration
### Loaders
@@ -254,13 +293,13 @@ Everything else is treated as `file`. `file` replaces the import with a URL (or
You can configure which loaders map to which extensions by passing `--loaders` to `bun`. For example:
-```
+```sh
bun --loader=.js:js
```
This will disable JSX transforms for `.js` files.
-#### CSS in JS
+### CSS in JS
When importing CSS in JavaScript-like loaders, CSS is treated special.
@@ -270,7 +309,7 @@ By default, Bun will transform a statement like this:
import "../styles/global.css";
```
-##### When `platform` is `browser`:
+##### When `platform` is `browser`
```js
globalThis.document?.dispatchEvent(
@@ -280,9 +319,9 @@ globalThis.document?.dispatchEvent(
);
```
-An event handler for turning that into a `<link>` is automatically registered when HMR is enabled. That event handler can be turned off either in a framework's `package.json` or by setting `globalThis["Bun_disableCSSImports"] = true;` in client-side code. Additionally, you can get a list of every .css file imported this way via `globalThis["__BUN"].allImportedStyles`.
+An event handler for turning that into a `<link>` is automatically registered when HMR is enabled. That event handler can be turned off either in a framework’s `package.json` or by setting `globalThis["Bun_disableCSSImports"] = true;` in client-side code. Additionally, you can get a list of every .css file imported this way via `globalThis["__BUN"].allImportedStyles`.
-##### When `platform` is `bun`:
+##### When `platform` is `bun`
```js
//@import url("http://localhost:3000/styles/globals.css");
@@ -296,7 +335,7 @@ addEventListener("fetch", async (event: FetchEvent) => {
const App = await import("pages/_app");
// This returns all .css files that were imported in the line above.
- // It's recursive, so any file that imports a CSS file will be included.
+ // It’s recursive, so any file that imports a CSS file will be included.
const appStylesheets = Bun.getImportedStyles();
// ...rest of code
@@ -307,7 +346,7 @@ This is useful for preventing flash of unstyled content.
### CSS Loader
-Bun bundles `.css` files imported via `@import` into a single file. It doesn't autoprefix or minify CSS today. Multiple `.css` files imported in one JavaScript file will _not_ be bundled into one file. You'll have to import those from a `.css` file.
+Bun bundles `.css` files imported via `@import` into a single file. It doesn’t autoprefix or minify CSS today. Multiple `.css` files imported in one JavaScript file will _not_ be bundled into one file. You’ll have to import those from a `.css` file.
This input:
@@ -328,17 +367,17 @@ Becomes:
/* ...contents of yo.css */
```
-#### CSS runtime
+### CSS runtime
-To support hot CSS reloading, Bun inserts `@supports` annotations into CSS that tag which files a stylesheet is composed of. Browsers ignore this, so it doesn't impact styles.
+To support hot CSS reloading, Bun inserts `@supports` annotations into CSS that tag which files a stylesheet is composed of. Browsers ignore this, so it doesn’t impact styles.
-By default, Bun's runtime code automatically listens to `onimportcss` and will insert the `event.detail` into a `<link rel="stylesheet" href={${event.detail}}>` if there is no existing `link` tag with that stylesheet. That's how Bun's equivalent of `style-loader` works.
+By default, Bun’s runtime code automatically listens to `onimportcss` and will insert the `event.detail` into a `<link rel="stylesheet" href={${event.detail}}>` if there is no existing `link` tag with that stylesheet. That’s how Bun’s equivalent of `style-loader` works.
### Frameworks
Frameworks preconfigure Bun to enable developers to use Bun with their existing tooling.
-Frameworks are configured via the `framework` object in the `package.json` of the framework (not in the application's `package.json`):
+Frameworks are configured via the `framework` object in the `package.json` of the framework (not in the application’s `package.json`):
Here is an example:
@@ -408,7 +447,7 @@ Here are type definitions:
```ts
type Framework = Environment & {
- // This changes what's printed in the console on load
+ // This changes what’s printed in the console on load
displayName?: string;
// This allows a prefix to be added (and ignored) to requests.
@@ -429,20 +468,20 @@ type Framework = Environment & {
// and replaces an imported object with a proxy that mimics CSS module support without doing any class renaming.
css?: "onimportcss" | "facade";
- // Bun's filesystem router
+ // Bun’s filesystem router
router?: Router;
};
type Define = {
// By passing ".env", Bun will automatically load .env.local, .env.development, and .env if exists in the project root
- // (in addition to the processes' environment variables)
+ // (in addition to the processes’ environment variables)
// When "*", all environment variables will be automatically injected into the JavaScript loader
// When a string like "NEXT_PUBLIC_", only environment variables starting with that prefix will be injected
".env": string | "*";
// These environment variables will be injected into the JavaScript loader
- // These are the equivalent of Webpack's resolve.alias and esbuild's --define.
+ // These are the equivalent of Webpack’s resolve.alias and esbuild’s --define.
// Values are parsed as JSON, so they must be valid JSON. The only exception is '' is a valid string, to simplify writing stringified JSON in JSON.
// If not set, `process.env.NODE_ENV` will be transformed into "development".
defaults: Record<string, string>;
@@ -462,7 +501,7 @@ type Environment = {
define?: Define;
};
-// Bun's filesystem router
+// Bun’s filesystem router
// Currently, Bun supports pages by either an absolute match or a parameter match.
// pages/index.tsx will be executed on navigation to "/" and "/index"
// pages/posts/[id].tsx will be executed on navigation to "/posts/123"
@@ -478,23 +517,25 @@ type Router = {
To use a framework, you pass `bun bun --use package-name`.
-Your framework's `package.json` `name` should start with `bun-framework-`. This is so that people can type something like `bun bun --use next` and it will check `bun-framework-next` first. This is similar to how Babel plugins tend to start with `babel-plugin-`.
+Your framework’s `package.json` `name` should start with `bun-framework-`. This is so that people can type something like `bun bun --use next` and it will check `bun-framework-next` first. This is similar to how Babel plugins tend to start with `babel-plugin-`.
For developing frameworks, you can also do `bun bun --use ./relative-path-to-framework`.
-If you're interested in adding a framework integration, please reach out. There's a lot here and it's not entirely documented yet.
+If you’re interested in adding a framework integration, please reach out. There’s a lot here and it’s not entirely documented yet.
+
+## Troubleshooting
-# FAQ
+### Bun not running on an M1 (or Apple Silicon)
-##### When running bun on an M1 (or Apple Silicon), if you see a message like this:
+If you see a message like this
> [1] 28447 killed bun create next ./test
-It most likely means you're running bun's x64 version on Apple Silicon. This happens if bun is running via Rosetta. Rosetta is unable to emulate AVX2 instructions, which Bun indirectly uses.
+It most likely means you’re running bun’s x64 version on Apple Silicon. This happens if bun is running via Rosetta. Rosetta is unable to emulate AVX2 instructions, which Bun indirectly uses.
The fix is to ensure you installed a version of Bun built for Apple Silicon.
-##### error: Unexpected
+### error: Unexpected
If you see an error like this:
@@ -502,15 +543,15 @@ If you see an error like this:
It usually means the max number of open file descriptors is being explicitly set to a low number. By default, Bun requests the max number of file descriptors available (which on macOS, is something like 32,000). But, if you previously ran into ulimit issues with e.g. Chokidar, someone on The Internet may have advised you to run `ulimit -n 8096`.
-That advice unfortunately **lowers** the hard limit to `8096`. This can be a problem in large repositories or projects with lots of dependencies. Chokidar (and other watchers) don't seem to call `setrlimit`, which means they're reliant on the (much lower) soft limit.
+That advice unfortunately **lowers** the hard limit to `8096`. This can be a problem in large repositories or projects with lots of dependencies. Chokidar (and other watchers) don’t seem to call `setrlimit`, which means they’re reliant on the (much lower) soft limit.
To fix this issue:
1. Remove any scripts that call `ulimit -n` and restart your shell.
2. Try agin, and if the error still occurs, try setting `ulimit -n` to an absurdly high number, such as `ulimit -n 65542`
-3. Try again, and if that still doesn't fix it, open an issue
+3. Try again, and if that still doesn’t fix it, open an issue
-# Reference
+## Reference
### `bun install`
@@ -520,50 +561,50 @@ Environment variables
| Name | Description |
| -------------------------------- | ------------------------------------------------------------- |
-| BUN_CONFIG_REGISTRY | Set an npm registry (default: https://registry.npmjs.org) |
+| BUN_CONFIG_REGISTRY | Set an npm registry (default: <https://registry.npmjs.org>) |
| BUN_CONFIG_TOKEN | Set an auth token (currently does nothing) |
| BUN_CONFIG_LOCKFILE_SAVE_PATH | File path to save the lockfile to (default: bun.lockb) |
| BUN_CONFIG_YARN_LOCKFILE | Save a Yarn v1-style yarn.lock |
| BUN_CONFIG_LINK_NATIVE_BINS | Point `bin` in package.json to a platform-specific dependency |
-| BUN_CONFIG_SKIP_SAVE_LOCKFILE | Don't save a lockfile |
-| BUN_CONFIG_SKIP_LOAD_LOCKFILE | Don't load a lockfile |
-| BUN_CONFIG_SKIP_INSTALL_PACKAGES | Don't install any packages |
+| BUN_CONFIG_SKIP_SAVE_LOCKFILE | Don’t save a lockfile |
+| BUN_CONFIG_SKIP_LOAD_LOCKFILE | Don’t load a lockfile |
+| BUN_CONFIG_SKIP_INSTALL_PACKAGES | Don’t install any packages |
-Bun always tries to use the fastest available installation method for the target platform. On macOS, that's `clonefile` and on Linux, that's `hardlink`. You can change which installation method is used with the `--backend` flag. When unavailable or on error, `clonefile` and `hardlink` fallsback to a platform-specific implementation of copying files.
+Bun always tries to use the fastest available installation method for the target platform. On macOS, that’s `clonefile` and on Linux, that’s `hardlink`. You can change which installation method is used with the `--backend` flag. When unavailable or on error, `clonefile` and `hardlink` fallsback to a platform-specific implementation of copying files.
Bun stores installed packages from npm in `~/.bun/install/cache/${name}@${version}`. Note that if the semver version has a `build` or a `pre` tag, it is replaced with a hash of that value instead. This is to reduce chances of errors from long file paths, but unfortunately complicates figuring out where a package was installed on disk.
When the `node_modules` folder exists, before installing, Bun checks if the `"name"` and `"version"` in `package/package.json` in the expected node_modules folder matches the expected `name` and `version`. This is how it determines whether or not it should install. It uses a custom JSON parser which stops parsing as soon as it finds `"name"` and `"version"`.
-When a `bun.lockb` doesn't exist or `package.json` has changed dependencies, tarballs are downloaded & extracted eagerly while resolving.
+When a `bun.lockb` doesn’t exist or `package.json` has changed dependencies, tarballs are downloaded & extracted eagerly while resolving.
-When a `bun.lockb` exists and `package.json` hasn't changed, Bun downloads missing dependencies lazily. If the package with a matching `name` & `version` already exists in the expected location within `node_modules`, Bun won't attempt to download the tarball.
+When a `bun.lockb` exists and `package.json` hasn’t changed, Bun downloads missing dependencies lazily. If the package with a matching `name` & `version` already exists in the expected location within `node_modules`, Bun won’t attempt to download the tarball.
-##### Platform-specific dependencies?
+#### Platform-specific dependencies?
-Bun stores normalized `cpu` and `os` values from npm in the lockfile, along with the resolved packages. It skips downloading, extracting, and installing packages disabled for the current target at runtime. This means the lockfile won't change between platforms/architectures even if the packages ultimately installed do change.
+Bun stores normalized `cpu` and `os` values from npm in the lockfile, along with the resolved packages. It skips downloading, extracting, and installing packages disabled for the current target at runtime. This means the lockfile won’t change between platforms/architectures even if the packages ultimately installed do change.
-##### Peer dependencies?
+#### Peer dependencies?
Peer dependencies are handled similarly to yarn. `bun install` does not automatically install peer dependencies and will try to choose an existing dependency.
#### Lockfile
-`bun.lockb` is Bun's binary lockfile format.
+`bun.lockb` is Bun’s binary lockfile format.
-##### Why is it binary?
+#### Why is it binary?
-In a word: Performance. Bun's lockfile saves & loads incredibly quickly, and saves a lot more data than what is typically inside lockfiles.
+In a word: Performance. Bun’s lockfile saves & loads incredibly quickly, and saves a lot more data than what is typically inside lockfiles.
-##### How do I inspect it?
+#### How do I inspect it?
For now, the easiest thing is to run `bun install -y`. That prints a Yarn v1-style yarn.lock file.
-##### What does the lockfile store?
+#### What does the lockfile store?
Packages, metadata for those packages, the hoisted install order, dependencies for each package, what packages those dependencies resolved to, an integrity hash (if available), what each package was resolved to and which version (or equivalent)
-##### Why is it fast?
+#### Why is it fast?
It uses linear arrays for all data. [Packages](https://github.com/Jarred-Sumner/bun/blob/be03fc273a487ac402f19ad897778d74b6d72963/src/install/install.zig#L1825) are referenced by auto-incrementing integer ID or a hash of the package name. Strings longer than 8 characters are de-duplicated. Prior to saving on disk, the lockfile is garbage-collected & made deterministic by walking the package tree and cloning the packages in dependency order.
@@ -575,12 +616,12 @@ To delete the cache:
rm -rf ~/.bun/install/cache
```
-##### npm registry metadata
+#### npm registry metadata
Bun uses a binary format for caching NPM registry responses. This loads much faster than JSON and tends to be smaller on disk.
-You will see these files in `~/.bun/install/cache/*.npm`. The filename pattern is `${hash(packageName)}.npm`. It's a hash so that extra directories don't need to be created for scoped packages
+You will see these files in `~/.bun/install/cache/*.npm`. The filename pattern is `${hash(packageName)}.npm`. It’s a hash so that extra directories don’t need to be created for scoped packages
-Bun's usage of `Cache-Control` ignores `Age`. This improves performance, but means Bun may be about 5 minutes out of date to receive the the latest package version metadata from npm.
+Bun’s usage of `Cache-Control` ignores `Age`. This improves performance, but means Bun may be about 5 minutes out of date to receive the the latest package version metadata from npm.
### `bun run`
@@ -631,7 +672,7 @@ react-scripts eject
If something is unexpected there, you can run `bun run env` to get a list of environment variables.
-The default shell it uses is `bash`, but if that's not found, it tries `sh` and if still not found, it tries `zsh`. This is not configurable right now, but if you care file an issue.
+The default shell it uses is `bash`, but if that’s not found, it tries `sh` and if still not found, it tries `zsh`. This is not configurable right now, but if you care file an issue.
`bun run` automatically adds any parent `node_modules/.bin` to `$PATH` and if no scripts match, it will load that binary instead. That means you can run executables from packages too.
@@ -641,7 +682,7 @@ bun run relay-compiler
# You can also do this, but:
# - It will only lookup packages in `node_modules/.bin` instead of `$PATH`
-# - It will start Bun's dev server if the script name doesn't exist (`bun` starts the dev server by default)
+# - It will start Bun’s dev server if the script name doesn’t exist (`bun` starts the dev server by default)
bun relay-compiler
```
@@ -652,7 +693,7 @@ To pass additional flags through to the task or executable, there are two ways:
bun run relay-compiler -- -–help
# Implicit: if you do not include "--", anything *after* the script name will be passed through
-# Bun flags are parsed first, which means e.g. `bun run relay-compiler --help` will print Bun's help instead of relay-compiler's help.
+# Bun flags are parsed first, which means e.g. `bun run relay-compiler --help` will print Bun’s help instead of relay-compiler’s help.
bun run relay-compiler --schema foo.graphql
```
@@ -700,13 +741,13 @@ bun create https://github.com/github-user/repo-name destination
bun create github.com/github-user/repo-name destination
```
-Note: you don't need `bun create` to use Bun. You don't need any configuration at all. This command exists to make it a little easier.
+Note: you don’t need `bun create` to use Bun. You don’t need any configuration at all. This command exists to make it a little easier.
-##### Local templates
+#### Local templates
If you have your own boilerplate you prefer using, copy it into `$HOME/.bun-create/my-boilerplate-name`.
-Before checking Bun's examples folder, `bun create` checks for a local folder matching the input in:
+Before checking Bun’s examples folder, `bun create` checks for a local folder matching the input in:
- `$BUN_CREATE_DIR/`
- `$HOME/.bun-create/`
@@ -735,7 +776,7 @@ bun create
Warning: unlike with remote templates, **bun will delete the entire destination folder if it already exists.**
-##### Flags
+#### Flags
| Flag | Description |
| ------------ | -------------------------------------- |
@@ -744,23 +785,23 @@ Warning: unlike with remote templates, **bun will delete the entire destination
| --pnpm | Use `pnpm` for tasks & install |
| --force | Overwrite existing files |
| --no-install | Skip installing `node_modules` & tasks |
-| --no-git | Don't initialize a git repository |
+| --no-git | Don’t initialize a git repository |
| --open | Start & open in-browser after finish |
| Environment Variables | Description |
| --------------------- | ------------------------------------------------------------------------------------------------------ |
-| GITHUB_API_DOMAIN | If you're using a GitHub enterprise or a proxy, you can change what the endpoint requests to GitHub go |
+| GITHUB_API_DOMAIN | If you’re using a GitHub enterprise or a proxy, you can change what the endpoint requests to GitHub go |
| GITHUB_API_TOKEN | This lets `bun create` work with private repositories or if you get rate-limited |
By default, `bun create` will cancel if there are existing files it would overwrite and its a remote template. You can pass `--force` to disable this behavior.
-##### Publishing a new template
+#### Publishing a new template
Clone this repository and a new folder in `examples/` with your new template. The `package.json` must have a `name` that starts with `@bun-examples/`. Do not worry about publishing it, that will happen automaticallly after the PR is merged.
-Make sure to include a `.gitignore` that includes `node_modules` so that `node_modules` aren't checked in to git when people download the template.
+Make sure to include a `.gitignore` that includes `node_modules` so that `node_modules` aren’t checked in to git when people download the template.
-##### Testing your new template
+#### Testing your new template
To test your new template, add it as a local template or pass the absolute path.
@@ -770,7 +811,7 @@ bun create /path/to/my/new/template destination-dir
Warning: **This will always delete everything in destination-dir**.
-##### Config
+#### Config
The `bun-create` section of `package.json` is automatically removed from the `package.json` on disk. This lets you add create-only steps without waiting for an extra package to install.
@@ -809,9 +850,9 @@ By default, all commands run inside the environment exposed by the auto-detected
Any command that starts with `"bun "` will be run without npm, relying on the first `bun` binary in `$PATH`.
-##### How `bun create` works
+#### How `bun create` works
-When you run `bun create ${template} ${destination}`, here's what happens:
+When you run `bun create ${template} ${destination}`, here’s what happens:
IF remote template
@@ -823,7 +864,7 @@ IF remote template
IF github repo
-1. Download the tarball from GitHub's API
+1. Download the tarball from GitHub’s API
2. Decompress & extract into `${destination}`
- If there are files that would overwrite, warn and exit unless `--force` is passed
@@ -856,12 +897,12 @@ ELSE IF local template
Run `bun bun ./path-to.js` to generate a `node_modules.bun` file containing all imported dependencies (recursively).
-**Why bundle?**
+#### Why bundle?
-- For browsers, loading entire apps without bundling dependencies is typically slow. With a fast bundler & transpiler, the bottleneck eventually becomes the web browser's ability to run many network requests concurrently. There are many workarounds for this. `<link rel="modulepreload">`, HTTP/3, etc but none are more effective than bundling. If you have reproducible evidence to the contrary, feel free to submit an issue. It would be better if bundling wasn't necessary.
-- On the server, bundling reduces the number of filesystem lookups to load JavaScript. While filesystem lookups are faster than HTTP requests, there's still overhead.
+- For browsers, loading entire apps without bundling dependencies is typically slow. With a fast bundler & transpiler, the bottleneck eventually becomes the web browser’s ability to run many network requests concurrently. There are many workarounds for this. `<link rel="modulepreload">`, HTTP/3, etc but none are more effective than bundling. If you have reproducible evidence to the contrary, feel free to submit an issue. It would be better if bundling wasn’t necessary.
+- On the server, bundling reduces the number of filesystem lookups to load JavaScript. While filesystem lookups are faster than HTTP requests, there’s still overhead.
-**What is `.bun`?**
+#### What is `.bun`?
The `.bun` file contains:
@@ -876,15 +917,15 @@ Here are some of the questions `.bun` files answer:
- what framework is used? (e.g. Next.js)
- where is the routes directory?
- how big is each imported dependency?
-- what is the hash of the bundle's contents? (for etags)
+- what is the hash of the bundle’s contents? (for etags)
- what is the name & version of every npm package exported in this bundle?
- what modules from which packages are used in this project? ("project" defined as all the entry points used to generate the .bun)
All in one file.
-It's a little like a build cache, but designed for reuse. I hope people will eventually check it into version control so their coworkers don't have to run `npm install` as often.
+It’s a little like a build cache, but designed for reuse. I hope people will eventually check it into version control so their coworkers don’t have to run `npm install` as often.
-##### Position-independent code
+#### Position-independent code
From a design perspective, the most important part of the `.bun` format is how code is organized. Each module is exported by a hash like this:
@@ -898,9 +939,9 @@ export var $eb6819b = $$m({
This makes bundled modules [position-independent](https://en.wikipedia.org/wiki/Position-independent_code). In theory, one could import only the exact modules in-use without reparsing code and without generating a new bundle. One bundle can dynamically become many bundles comprising only the modules in use on the webpage. Thanks to the metadata with the byte offsets, a web server can send each module to browsers [zero-copy](https://en.wikipedia.org/wiki/Zero-copy) using [sendfile](https://man7.org/linux/man-pages/man2/sendfile.2.html). Bun itself is not quite this smart yet, but these optimizations would be useful in production and potentially very useful for React Server Components.
-To see the schema inside, have a look at [`JavascriptBundleContainer`](./src/api/schema.d.ts#:~:text=export%20interface-,JavascriptBundleContainer,-%7B). You can find JavaScript bindings to read the metadata in [src/api/schema.js](./src/api/schema.js). This is not really an API yet. It's missing the part where it gets the binary data from the bottom of the file. Someday, I want this to be usable by other tools too.
+To see the schema inside, have a look at [`JavascriptBundleContainer`](./src/api/schema.d.ts#:~:text=export%20interface-,JavascriptBundleContainer,-%7B). You can find JavaScript bindings to read the metadata in [src/api/schema.js](./src/api/schema.js). This is not really an API yet. It’s missing the part where it gets the binary data from the bottom of the file. Someday, I want this to be usable by other tools too.
-**Where is the code?**
+#### Where is the code?
`.bun` files are marked as executable.
@@ -918,15 +959,15 @@ This works because every `.bun` file starts with this:
#!/usr/bin/env bun
```
-To deploy to production with Bun, you'll want to get the code from the `.bun` file and stick that somewhere your web server can find it (or if you're using Vercel or a Rails app, in a `public` folder).
+To deploy to production with Bun, you’ll want to get the code from the `.bun` file and stick that somewhere your web server can find it (or if you’re using Vercel or a Rails app, in a `public` folder).
Note that `.bun` is a binary file format, so just opening it in VSCode or vim might render strangely.
-**Advanced**
+#### Advanced
By default, `bun bun` only bundles external dependencies that are `import`ed or `require`d in either app code or another external dependency. An "external depenendency" is defined as, "A JavaScript-like file that has `/node_modules/` in the resolved file path and a corresponding `package.json`".
-To force bun to bundle packages which are not located in a `node_modules` folder (i.e. the final, resolved path following all symlinks), add a `bun` section to the root project's `package.json` with `alwaysBundle` set to an array of package names to always bundle. Here's an example:
+To force bun to bundle packages which are not located in a `node_modules` folder (i.e. the final, resolved path following all symlinks), add a `bun` section to the root project’s `package.json` with `alwaysBundle` set to an array of package names to always bundle. Here’s an example:
```json
{
@@ -937,9 +978,9 @@ To force bun to bundle packages which are not located in a `node_modules` folder
}
```
-Bundled dependencies are not eligible for Hot Module Reloading. The code is served to browsers & Bun.js verbatim. But, in the future, it may be sectioned off into only parts of the bundle being used. That's possible in the current version of the `.bun` file (so long as you know which files are necessary), but it's not implemented yet. Longer-term, it will include all `import` and `export` of each module inside.
+Bundled dependencies are not eligible for Hot Module Reloading. The code is served to browsers & Bun.js verbatim. But, in the future, it may be sectioned off into only parts of the bundle being used. That’s possible in the current version of the `.bun` file (so long as you know which files are necessary), but it’s not implemented yet. Longer-term, it will include all `import` and `export` of each module inside.
-**What is the module ID hash?**
+#### What is the module ID hash?
The `$eb6819b` hash used here:
@@ -953,25 +994,25 @@ Is generated like this:
2. Wyhash 64 of the `package.hash` + `package_path`. `package_path` means "relative to the root of the npm package, where is the module imported?". For example, if you imported `react/jsx-dev-runtime.js`, the `package_path` is `jsx-dev-runtime.js`. `react-dom/cjs/react-dom.development.js` would be `cjs/react-dom.development.js`
3. Truncate the hash generated above to a `u32`
-The implementation details of this module ID hash will vary between versions of Bun. The important part is the metadata contains the module IDs, the package paths, and the package hashes so it shouldn't really matter in practice if other tooling wants to make use of any of this.
+The implementation details of this module ID hash will vary between versions of Bun. The important part is the metadata contains the module IDs, the package paths, and the package hashes so it shouldn’t really matter in practice if other tooling wants to make use of any of this.
### `bun completions`
-This command installs completions for `zsh` and/or `fish`. It's run automatically on every `bun upgrade` and on install. It reads from `$SHELL` to determine which shell to install for. It tries several common shell completion directories for your shell and OS.
+This command installs completions for `zsh` and/or `fish`. It’s run automatically on every `bun upgrade` and on install. It reads from `$SHELL` to determine which shell to install for. It tries several common shell completion directories for your shell and OS.
If you want to copy the completions manually, run `bun completions > path-to-file`. If you know the completions directory to install them to, run `bun completions /path/to/directory`.
-### Environment variables
+## Environment variables
-- `GOMAXPROCS`: For `bun bun`, this sets the maximum number of threads to use. If you're experiencing an issue with `bun bun`, try setting `GOMAXPROCS=1` to force bun to run single-threaded
-- `DISABLE_BUN_ANALYTICS=1` this disables Bun's analytics. Bun records bundle timings (so we can answer with data, "is bun getting faster?") and feature usage (e.g. "are people actually using macros?"). The request body size is about 60 bytes, so it's not a lot of data
+- `GOMAXPROCS`: For `bun bun`, this sets the maximum number of threads to use. If you’re experiencing an issue with `bun bun`, try setting `GOMAXPROCS=1` to force bun to run single-threaded
+- `DISABLE_BUN_ANALYTICS=1` this disables Bun’s analytics. Bun records bundle timings (so we can answer with data, "is bun getting faster?") and feature usage (e.g. "are people actually using macros?"). The request body size is about 60 bytes, so it’s not a lot of data
- `TMPDIR`: Before `bun bun` completes, it stores the new `.bun` in `$TMPDIR`. If unset, `TMPDIR` defaults to the platform-specific temporary directory (on Linux, `/tmp` and on macOS `/private/tmp`)
-# Credits
+## Credits
-- While written in Zig instead of Go, Bun's JS transpiler, CSS lexer, and node module resolver source code is based off of @evanw's esbuild project. @evanw did a fantastic job with esbuild.
+- While written in Zig instead of Go, Bun’s JS transpiler, CSS lexer, and node module resolver source code is based off of @evanw’s esbuild project. @evanw did a fantastic job with esbuild.
-# License
+## License
Bun itself is MIT-licensed.
@@ -979,29 +1020,29 @@ However, JavaScriptCore (and WebKit) is LGPL-2 and Bun statically links it.
Per LGPL2:
-> (1) If you statically link against an LGPL'd library, you must also provide your application in an object (not necessarily source) format, so that a user has the opportunity to modify the library and relink the application.
+> (1) If you statically link against an LGPL’d library, you must also provide your application in an object (not necessarily source) format, so that a user has the opportunity to modify the library and relink the application.
-You can find the patched version of WebKit used by Bun here: https://github.com/jarred-sumner/webkit. If you would like to relink Bun with changes:
+You can find the patched version of WebKit used by Bun here: <https://github.com/jarred-sumner/webkit>. If you would like to relink Bun with changes:
- `git submodule update --init --recursive`
- `make jsc`
- `zig build`
-This compiles JavaScriptCore, compiles Bun's `.cpp` bindings for JavaScriptCore (which are the object files using JavaScriptCore) and outputs a new `bun` binary with your changes.
+This compiles JavaScriptCore, compiles Bun’s `.cpp` bindings for JavaScriptCore (which are the object files using JavaScriptCore) and outputs a new `bun` binary with your changes.
-To successfully run `zig build`, you will need to install a patched version of Zig available here: https://github.com/jarred-sumner/zig/tree/jarred/zig-sloppy.
+To successfully run `zig build`, you will need to install a patched version of Zig available here: <https://github.com/jarred-sumner/zig/tree/jarred/zig-sloppy>.
Bun also statically links these libraries:
-- `libicu` 66.1, which can be found here: https://github.com/unicode-org/icu/blob/main/icu4c/LICENSE
+- `libicu` 66.1, which can be found here: <https://github.com/unicode-org/icu/blob/main/icu4c/LICENSE>
- [`picohttp`](https://github.com/h2o/picohttpparser), which is dual-licensed under the Perl License or the MIT License
- [`mimalloc`](https://github.com/microsoft/mimalloc), which is MIT licensed
- [`zlib-cloudflare`](https://github.com/cloudflare/zlib), which is zlib licensed
- [`boringssl`](https://boringssl.googlesource.com/boringssl/), which has [several licenses](https://boringssl.googlesource.com/boringssl/+/refs/heads/master/LICENSE)
- [`libarchive`](https://github.com/libarchive/libarchive), which has [several licenses](https://github.com/libarchive/libarchive/blob/master/COPYING)
-- [`libiconv`](https://www.gnu.org/software/libiconv/), which is LGPL2. It's a dependency of libarchive.
+- [`libiconv`](https://www.gnu.org/software/libiconv/), which is LGPL2. It’s a dependency of libarchive.
-For compatibiltiy reasons, these NPM packages are embedded into Bun's binary and injected if imported.
+For compatibiltiy reasons, these NPM packages are embedded into Bun’s binary and injected if imported.
- [`assert`](https://npmjs.com/package/assert) (MIT license)
- [`browserify-zlib`](https://npmjs.com/package/browserify-zlib) (MIT license)
@@ -1025,11 +1066,11 @@ For compatibiltiy reasons, these NPM packages are embedded into Bun's binary and
- [`util`](https://npmjs.com/package/util) (MIT license)
- [`vm-browserify`](https://npmjs.com/package/vm-browserify) (MIT license)
-# Developing Bun
+## Developing Bun
Estimated: 30-90 minutes :(
-## macOS
+### MacOS
Install LLVM 12 and homebrew dependencies:
@@ -1055,7 +1096,7 @@ export CPPFLAGS="$CPPFLAGS -I$(brew --prefix llvm@12)/include"
On fish that looks like `fish_add_path (brew --prefix llvm@12)/bin`
-### Compile Zig
+#### Compile Zig (macOS)
```bash
git clone https://github.com/jarred-sumner/zig
@@ -1064,17 +1105,17 @@ git checkout jarred/zig-sloppy-with-small-structs
cmake . -DCMAKE_PREFIX_PATH=$(brew --prefix llvm@12) -DZIG_STATIC_LLVM=ON -DCMAKE_BUILD_TYPE=Release && make -j 16
```
-Note that `brew install zig` won't work. Bun uses a build of Zig with a couple patches.
+Note that `brew install zig` won’t work. Bun uses a build of Zig with a couple patches.
-Additionally, you'll need `cmake`, `npm` and `esbuild` installed globally.
+Additionally, you’ll need `cmake`, `npm` and `esbuild` installed globally.
-You'll want to make sure `zig` is in `$PATH`. The `zig` binary wil be in the same folder as the newly-cloned `zig` repo. If you use fish, you can run `fish_add_path (pwd)`.
+You’ll want to make sure `zig` is in `$PATH`. The `zig` binary wil be in the same folder as the newly-cloned `zig` repo. If you use fish, you can run `fish_add_path (pwd)`.
-### Build bun
+#### Build bun (macOS)
-If you're building on an Apple Silicon device, you'll need to do is ensure you have set an environment variable `CODESIGN_IDENTITY`. You can find the correct value by visiting `Keychain Access` and looking under your `login` profile for `Certificates`. The name would usually look like `Apple Development: user@example.com (WDYABC123)`
+If you’re building on an Apple Silicon device, you’ll need to do is ensure you have set an environment variable `CODESIGN_IDENTITY`. You can find the correct value by visiting `Keychain Access` and looking under your `login` profile for `Certificates`. The name would usually look like `Apple Development: user@example.com (WDYABC123)`
-If you're not familiar with the process, there's a guide [here](https://ioscodesigning.com/generating-code-signing-files/#generate-a-code-signing-certificate-using-xcode)
+If you’re not familiar with the process, there’s a guide [here](https://ioscodesigning.com/generating-code-signing-files/#generate-a-code-signing-certificate-using-xcode)
In `bun`:
@@ -1084,7 +1125,7 @@ git submodule update --init --recursive --progress --depth=1
make vendor jsc identifier-cache dev
```
-### Verify it worked
+#### Verify it worked (macOS)
First ensure the node dependencies are installed
@@ -1096,12 +1137,12 @@ npm i
Then
```bash
-# if you're not already in the bun root directory
+# if you’re not already in the bun root directory
cd ../../
make test-dev-all
```
-### Troubleshooting
+#### Troubleshooting (macOS)
If you see an error when compiling `libarchive`, run this:
@@ -1111,11 +1152,11 @@ brew install pkg-config
If you see an error about missing files on `zig build obj`, make sure you built the headers
-## Linux
+### Linux
-A Dockerfile with the exact version of Zig used is availble at `Dockerfile.zig`. This installs all the system dependencies you'll need excluding JavaScriptCore, but doesn't currently compile Bun in one command. If you're having trouble compiling Zig, it might be helpful to look at.
+A Dockerfile with the exact version of Zig used is availble at `Dockerfile.zig`. This installs all the system dependencies you’ll need excluding JavaScriptCore, but doesn’t currently compile Bun in one command. If you’re having trouble compiling Zig, it might be helpful to look at.
-Compile Zig:
+#### Compile Zig (Linux)
```bash
git clone https://github.com/jarred-sumner/zig
@@ -1124,7 +1165,7 @@ git checkout jarred/zig-sloppy-with-small-structs
cmake . -DCMAKE_BUILD_TYPE=Release && make -j $(nproc)
```
-Compile JavaScriptCore:
+#### Compile JavaScriptCore (Linux)
```bash
# This will take a few minutes, depending on how fast your internet is
@@ -1140,13 +1181,13 @@ docker container ls
docker cp DOCKER_CONTAINER_ID_YOU_JUST_FOUND:/output $HOME/webkit-build
```
-Compile Bun:
+#### Build Bun (Linux)
```bash
make vendor dev
```
-### Verify it worked
+#### Verify it worked (Lunux)
First ensure the node dependencies are installed
@@ -1158,7 +1199,7 @@ npm i
Then
```bash
-# if you're not already in the bun root directory
+# if you’re not already in the bun root directory
cd ../../
make test-dev-all
```