mirror of
https://github.com/oven-sh/bun
synced 2026-02-02 15:08:46 +00:00
Bundler docs updates + support for naming string (#2767)
* Bundler docs updates * Remove comments * Updates * Fix bunx usages * Add info about metafile
This commit is contained in:
@@ -1,136 +1,234 @@
|
||||
The Bun bundler implements a set of default loaders out of the box. As a rule of thumb, the bundler and the runtime both support the same set of file types out of the box.
|
||||
|
||||
`.js` `.cjs` `.mjs` `.mts` `.cts` `.ts` `.tsx` `.jsx` `.toml` `.json`
|
||||
`.js` `.cjs` `.mjs` `.mts` `.cts` `.ts` `.tsx` `.jsx` `.toml` `.json` `.txt` `.wasm` `.node`
|
||||
|
||||
{% callout %}
|
||||
The runtime also supports `.wasm` and `.node` binaries, which are not easily embedded in a bundle. These are effectively not supported by Bun's bundler.
|
||||
{% /callout %}
|
||||
Bun uses the file extension to determine which built-in _loader_ should be used to parse the file. Every loader has a name, such as `js`, `tsx`, or `json`. These names are used when building [plugins](/docs/bundler/plugins) that extend Bun with custom loaders.
|
||||
|
||||
This document describes how these extensions map onto Bun's set of built-in _loaders_. Every loader has a name, such as `js`, `tsx`, or `json`. These names are used when building [plugins](/docs/bundler/plugins) that extend Bun with custom loaders.
|
||||
## Built-in loaders
|
||||
|
||||
### `js`
|
||||
|
||||
**JavaScript**. Default for `.cjs` and `.mjs`.
|
||||
|
||||
Parses the code and applies a set if default transforms, like dead-code elimination, tree shaking, and environment variable inlining. Note that Bun does not attempt to down-convert syntax at the moment.
|
||||
|
||||
### `jsx`
|
||||
|
||||
**JavaScript + JSX.**. Default for `.js` and `.jsx`.
|
||||
|
||||
Same as the `js` loader, but JSX syntax is supported. By default, JSX is downconverted to plain JavaScript; the details of how this is done depends on the `jsx*` compiler options in your `tsconfig.json`. Refer to the TypeScript documentation [on JSX](https://www.typescriptlang.org/docs/handbook/jsx.html) for more information.
|
||||
|
||||
### `ts`
|
||||
|
||||
**TypeScript loader**. Default for `.ts`, `.mts`, and `.cts`.
|
||||
|
||||
Strips out all TypeScript syntax, then behaves identically to the `js` loader. Bun does not perform typechecking.
|
||||
|
||||
### `tsx`
|
||||
|
||||
**TypeScript + JSX loader**. Default for `.tsx`. Transpiles both TypeScript and JSX to vanilla JavaScript.
|
||||
|
||||
### `json`
|
||||
|
||||
**JSON loader**. Default for `.json`.
|
||||
|
||||
JSON files can be directly imported.
|
||||
|
||||
```ts
|
||||
import pkg from "./package.json";
|
||||
pkg.name; // => "my-package"
|
||||
```
|
||||
|
||||
During bundling, the parsed JSON is inlined into the bundle as a JavaScript object.
|
||||
|
||||
```ts
|
||||
var pkg = {
|
||||
name: "my-package",
|
||||
// ... other fields
|
||||
};
|
||||
pkg.name;
|
||||
```
|
||||
|
||||
If a `.json` file is passed as an entrypoint to the bundler, it will be converted to a `.js` module that `export default`s the parsed object.
|
||||
|
||||
{% codetabs %}
|
||||
|
||||
```json#Input
|
||||
{
|
||||
"name": "John Doe",
|
||||
"age": 35,
|
||||
"email": "johndoe@example.com"
|
||||
}
|
||||
```
|
||||
|
||||
```js#Output
|
||||
export default {
|
||||
name: "John Doe",
|
||||
age: 35,
|
||||
email: "johndoe@example.com"
|
||||
}
|
||||
```
|
||||
|
||||
{% /codetabs %}
|
||||
|
||||
### `toml`
|
||||
|
||||
**TOML loader**. Default for `.toml`.
|
||||
|
||||
TOML files can be directly imported. Bun will parse them with its fast native TOML parser.
|
||||
|
||||
```ts
|
||||
import config from "./bunfig.toml";
|
||||
config.logLevel; // => "debug"
|
||||
```
|
||||
|
||||
During bundling, the parsed TOML is inlined into the bundle as a JavaScript object.
|
||||
|
||||
```ts
|
||||
var config = {
|
||||
logLevel: "debug",
|
||||
// ...other fields
|
||||
};
|
||||
config.logLevel;
|
||||
```
|
||||
|
||||
If a `.toml` file is passed as an entrypoint, it will be converted to a `.js` module that `export default`s the parsed object.
|
||||
|
||||
{% codetabs %}
|
||||
|
||||
```toml#Input
|
||||
name = "John Doe"
|
||||
age = 35
|
||||
email = "johndoe@example.com"
|
||||
```
|
||||
|
||||
```js#Output
|
||||
export default {
|
||||
name: "John Doe",
|
||||
age: 35,
|
||||
email: "johndoe@example.com"
|
||||
}
|
||||
```
|
||||
|
||||
{% /codetabs %}
|
||||
|
||||
### `text`
|
||||
|
||||
**Text loader**. Default for `.txt`.
|
||||
|
||||
The contents of the text file are read and inlined into the bundle as a string.
|
||||
Text files can be directly imported. The file is read and returned as a string.
|
||||
|
||||
```ts
|
||||
import contents from "./file.txt";
|
||||
console.log(contents); // => "Hello, world!"
|
||||
```
|
||||
|
||||
When referenced during a build, the contents are into the bundle as a string.
|
||||
|
||||
```ts
|
||||
var contents = `Hello, world!`;
|
||||
console.log(contents);
|
||||
```
|
||||
|
||||
If a `.txt` file is passed as an entrypoint, it will be converted to a `.js` module that `export default`s the file contents.
|
||||
|
||||
{% codetabs %}
|
||||
|
||||
```txt#Input
|
||||
Hello, world!
|
||||
```
|
||||
|
||||
```js#Output
|
||||
export default "Hello, world!";
|
||||
```
|
||||
|
||||
{% /codetabs %}
|
||||
|
||||
### `wasm`
|
||||
|
||||
**WebAssembly loader**. Default for `.wasm`.
|
||||
|
||||
In the runtime, WebAssembly files can be directly imported. The file is read and returned as a `WebAssembly.Module`.
|
||||
|
||||
```ts
|
||||
import wasm from "./module.wasm";
|
||||
console.log(wasm); // => WebAssembly.Module
|
||||
```
|
||||
|
||||
In the bundler, `.wasm` files are handled using the [`file`](#file) loader.
|
||||
|
||||
### `napi`
|
||||
|
||||
**Native addon loader**. Default for `.node`.
|
||||
|
||||
In the runtime, native addons can be directly imported.
|
||||
|
||||
```ts
|
||||
import addon from "./addon.node";
|
||||
console.log(addon);
|
||||
```
|
||||
|
||||
In the bundler, `.node` files are handled using the [`file`](#file) loader.
|
||||
|
||||
### `file`
|
||||
|
||||
**File loader**. Default for all unrecognized file types.
|
||||
|
||||
The file loader resolves the import as a _path/URL_ to the imported file. It's commonly used for referencing media or font assets.
|
||||
|
||||
```ts#logo.ts
|
||||
import logo from "./logo.svg";
|
||||
console.log(logo);
|
||||
```
|
||||
|
||||
_In the runtime_, Bun checks that the `logo.svg` file exists and converts it to an absolute path to the location of `logo.svg` on disk.
|
||||
|
||||
```bash
|
||||
$ bun run logo.ts
|
||||
/path/to/project/logo.svg
|
||||
```
|
||||
|
||||
_In the bundler_, things are slightly different. The file is copied into `outdir` as-is, and the import is resolved as a relative path pointing to the copied file.
|
||||
|
||||
```ts#Output
|
||||
var logo = "./logo.svg";
|
||||
console.log(logo);
|
||||
```
|
||||
|
||||
If a value is specified for `publicPath`, the import will use value as a prefix to construct an absolute path/URL.
|
||||
|
||||
{% table %}
|
||||
|
||||
- Loader
|
||||
- Extensions
|
||||
- Description
|
||||
- Public path
|
||||
- Resolved import
|
||||
|
||||
---
|
||||
|
||||
- `js`
|
||||
- `.cjs` `.mjs`
|
||||
- **JavaScript.** Parses the code and applies a set if default transforms, like dead-code elimination, tree shaking, and environment variable inlining. Note that Bun does not attempt to down-convert syntax at the moment.
|
||||
- `""` (default)
|
||||
- `/logo.svg`
|
||||
|
||||
---
|
||||
|
||||
- `jsx`
|
||||
- `.js` `.jsx`
|
||||
- **JavaScript + JSX.** Same as the `js` loader, but JSX syntax is supported. By default, JSX is downconverted to `createElement` syntax and a `jsx` factory is injected into the bundle. This can be configured using the relevant `jsx*` compiler options in `tsconfig.json`.
|
||||
- `"/assets"`
|
||||
- `/assets/logo.svg`
|
||||
|
||||
---
|
||||
|
||||
- `ts`
|
||||
- `.mts` `.cts`
|
||||
- **TypeScript.** Strips out all TypeScript syntax, then behaves identically to the `js` loader. Bun does not perform typechecking.
|
||||
|
||||
---
|
||||
|
||||
- `tsx`
|
||||
- `.ts` `.tsx`
|
||||
- **TypeScript + JSX**. Transpiles both TypeScript and JSX to vanilla JavaScript.
|
||||
|
||||
---
|
||||
|
||||
- `json`
|
||||
- `.json`
|
||||
- **JSON**. JSON files are parsed and inlined into the bundle as a JavaScript object.
|
||||
|
||||
```ts
|
||||
import pkg from "./package.json";
|
||||
pkg.name; // => "my-package"
|
||||
```
|
||||
|
||||
If a `.json` file is passed as an entrypoint, it will be converted to a `.js` with the parsed object as a default export.
|
||||
|
||||
{% codetabs %}
|
||||
|
||||
```json#Input
|
||||
{
|
||||
"name": "John Doe",
|
||||
"age": 35,
|
||||
"email": "johndoe@example.com"
|
||||
}
|
||||
```
|
||||
|
||||
```js#Output
|
||||
export default {
|
||||
name: "John Doe",
|
||||
age: 35,
|
||||
email: "johndoe@example.com"
|
||||
}
|
||||
```
|
||||
|
||||
{% /codetabs %}
|
||||
|
||||
---
|
||||
|
||||
- `toml`
|
||||
- `.toml`
|
||||
- **TOML**. TOML files are parsed and inlined into the bundle as a JavaScript object.
|
||||
|
||||
```ts
|
||||
import config from "./bunfig.toml";
|
||||
config.logLevel; // => "debug"
|
||||
```
|
||||
|
||||
If a `.toml` file is passed as an entrypoint, it will be converted to a `.js` with the parsed object as a default export.
|
||||
|
||||
{% codetabs %}
|
||||
|
||||
```toml#Input
|
||||
name = "John Doe"
|
||||
age = 35
|
||||
email = "johndoe@example.com"
|
||||
```
|
||||
|
||||
```js#Output
|
||||
export default {
|
||||
name: "John Doe",
|
||||
age: 35,
|
||||
email: "johndoe@example.com"
|
||||
}
|
||||
```
|
||||
|
||||
{% /codetabs %}
|
||||
|
||||
---
|
||||
|
||||
- `text`
|
||||
- `.txt`
|
||||
- **Text files**. The contents of the text file are read and inlined into the bundle as a string.
|
||||
|
||||
```ts
|
||||
import contents from "./file.txt";
|
||||
console.log(contents); // => "Hello, world!"
|
||||
```
|
||||
|
||||
If a `.txt` file is passed as an entrypoint, it will be converted to a `.js` with the contents of the file as a default export.
|
||||
|
||||
{% codetabs %}
|
||||
|
||||
```txt#Input
|
||||
Hello, world!
|
||||
```
|
||||
|
||||
```js#Output
|
||||
export default "Hello, world!";
|
||||
```
|
||||
|
||||
{% /codetabs %}
|
||||
|
||||
---
|
||||
|
||||
- `file`
|
||||
- `.*`
|
||||
- **File loader**. Any unrecognized file type is handled using the `file` loader. The file is copied into the `outdir` as-is. The name of the copied file is determined using the value of `naming.asset`.
|
||||
- `"https://cdn.example.com/"`
|
||||
- `https://cdn.example.com/`
|
||||
|
||||
{% /table %}
|
||||
|
||||
{% callout %}
|
||||
The location and file name of the copied file is determined by the value of [`naming.asset`](/docs/cli/build#naming).
|
||||
{% callout %}
|
||||
This loader is copied into the `outdir` as-is. The name of the copied file is determined using the value of `naming.asset`.
|
||||
|
||||
{% details summary="Fixing TypeScript import errors" %}
|
||||
If you're using TypeScript, you may get an error like this:
|
||||
|
||||
```ts
|
||||
// TypeScript error
|
||||
// Cannot find module './logo.svg' or its corresponding type declarations.
|
||||
```
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{% callout %}
|
||||
**Note** — Added in Bun v0.6.0
|
||||
**Note** — Available in the Bun v0.6.0 nightly. Run `bun upgrade --canary` to try it out.
|
||||
{% /callout %}
|
||||
|
||||
Bun's fast native bundler is now in beta. It can be used via the `bun build` CLI command or the `Bun.build()` JavaScript API.
|
||||
@@ -58,7 +58,7 @@ To create our bundle:
|
||||
{% codetabs %}
|
||||
|
||||
```ts#JavaScript
|
||||
Bun.build({
|
||||
await Bun.build({
|
||||
entrypoints: ['./index.tsx'],
|
||||
outdir: './out',
|
||||
})
|
||||
@@ -70,12 +70,7 @@ $ bun build ./index.tsx --outdir ./out
|
||||
|
||||
{% /codetabs %}
|
||||
|
||||
Let's break that down.
|
||||
|
||||
- `entrypoints` — **Required.** An array of paths corresponding to the entrypoints of our application. In this case, we just have one.
|
||||
- `outdir` — **Required.** The directory where output files will be written.
|
||||
|
||||
Running this build will generate a new file `./out/index.js`.
|
||||
For each file specified in `entrypoints`, Bun will generate a new bundle. This bundle will be written to disk in the `./out` directory (as resolved from the current working directory). After running the build, the file system looks like this:
|
||||
|
||||
```ts
|
||||
.
|
||||
@@ -85,18 +80,18 @@ Running this build will generate a new file `./out/index.js`.
|
||||
└── index.js
|
||||
```
|
||||
|
||||
It looks something like this:
|
||||
The contents of the `out/index.js` file looks something like this:
|
||||
|
||||
```js#out/index.js
|
||||
// ...
|
||||
// ~20k lines of code
|
||||
// including the contents of `react-dom/client` and all its dependencies
|
||||
// this is where the $jsx and $createRoot functions are defined
|
||||
// this is where the $jsxDEV and $createRoot functions are defined
|
||||
|
||||
|
||||
// Component.tsx
|
||||
function Component(props) {
|
||||
return $jsx("p", {
|
||||
return $jsxDEV("p", {
|
||||
children: props.message
|
||||
}, undefined, false, undefined, this);
|
||||
}
|
||||
@@ -104,7 +99,7 @@ function Component(props) {
|
||||
// index.tsx
|
||||
var rootNode = document.getElementById("root");
|
||||
var root = $createRoot(rootNode);
|
||||
root.render($jsx(Component, {
|
||||
root.render($jsxDEV(Component, {
|
||||
message: "Sup!"
|
||||
}, undefined, false, undefined, this));
|
||||
```
|
||||
@@ -181,58 +176,42 @@ Like the Bun runtime, the bundler supports an array of file types out of the box
|
||||
console.log(contents); // => "Hello, world!"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
- `.*`
|
||||
- If the bundler encounters a file with an unsupported extension, it treats it as an _external file_. That means the import is converted into a path, and the referenced file is copied into the `outdir` as-is.
|
||||
|
||||
{% codetabs %}
|
||||
|
||||
```ts#Build_file
|
||||
Bun.build({
|
||||
entrypoints: ['./index.ts'],
|
||||
outdir: './out',
|
||||
origin: 'https://example.com',
|
||||
})
|
||||
```
|
||||
|
||||
```ts#Input
|
||||
import logo from "./logo.svg";
|
||||
console.log(logo);
|
||||
```
|
||||
|
||||
```ts#Output
|
||||
var logo = "./logo-ab237dfe.svg";
|
||||
console.log(logo);
|
||||
```
|
||||
|
||||
{% /codetabs %}
|
||||
|
||||
By default, a hash is added to the file name to avoid collisions; this behavior can be overridden with the [`naming.asset`](#naming) option.
|
||||
|
||||
If a value is provided for `origin`, the bundler will construct an absolute URL instead of using a relative path.
|
||||
|
||||
{% codetabs %}
|
||||
|
||||
```ts-diff#Build_file
|
||||
Bun.build({
|
||||
entrypoints: ['./index.ts'],
|
||||
outdir: './out',
|
||||
+ origin: 'https://example.com',
|
||||
})
|
||||
```
|
||||
|
||||
```ts-diff#Output
|
||||
- var logo = "./logo-ab237dfe.svg";
|
||||
+ var logo = "https://example.com/logo-ab237dfe.svg";
|
||||
console.log(logo);
|
||||
```
|
||||
|
||||
{% /codetabs %}
|
||||
|
||||
{% /table %}
|
||||
|
||||
The behavior described in this table can be overridden with [plugins](/docs/bundler/plugins). Refer to the [Bundler > Loaders](/docs/bundler/loaders) page for complete documentation on Bun's built-in loaders.
|
||||
### Assets
|
||||
|
||||
If the bundler encounters an import with an unrecognized extension, it treats the imported file as an _external file_. The referenced file is copied as-is into `outdir`, and the import is resolved as a _path_ to the file.
|
||||
|
||||
{% codetabs %}
|
||||
|
||||
```ts#Build_file
|
||||
await Bun.build({
|
||||
entrypoints: ['./index.ts'],
|
||||
outdir: './out'
|
||||
})
|
||||
```
|
||||
|
||||
```ts#Input
|
||||
import logo from "./logo.svg";
|
||||
console.log(logo);
|
||||
```
|
||||
|
||||
```ts#Output
|
||||
var logo = "./logo-ab237dfe.svg";
|
||||
console.log(logo);
|
||||
```
|
||||
|
||||
{% /codetabs %}
|
||||
|
||||
{% callout %}
|
||||
The exact behavior of the file loader is also impacted by [`naming`](#naming) and [`publicPath`](#publicpath).
|
||||
{% /callout %}
|
||||
|
||||
Refer to the [Bundler > Loaders](/docs/bundler/loaders#file) page for more complete documentation on the file loader.
|
||||
|
||||
### Plugins
|
||||
|
||||
The behavior described in this table can be overridden with [plugins](/docs/bundler/plugins). Refer to the [Bundler > Loaders](/docs/bundler/plugins) page for complete documentation.
|
||||
|
||||
## API
|
||||
|
||||
@@ -240,9 +219,65 @@ The behavior described in this table can be overridden with [plugins](/docs/bund
|
||||
|
||||
**Required.** An array of paths corresponding to the entrypoints of our application. One bundle will be generated for each entrypoint.
|
||||
|
||||
{% codetabs %}
|
||||
|
||||
```ts#JavaScript
|
||||
const result = await Bun.build({
|
||||
entrypoints: ['./index.ts']
|
||||
}); // => Promise
|
||||
|
||||
await result;
|
||||
// => { outputs: Array<{ path: string; result: Blob }> }
|
||||
```
|
||||
|
||||
```bash#CLI
|
||||
$ bun build --entrypoints ./index.ts
|
||||
# the bundle will be printed to stdout
|
||||
# <bundled code>
|
||||
```
|
||||
|
||||
{% /codetabs %}
|
||||
|
||||
### `outdir`
|
||||
|
||||
**Required.** The directory where output files will be written.
|
||||
The directory where output files will be written.
|
||||
|
||||
{% codetabs %}
|
||||
|
||||
```ts#JavaScript
|
||||
const result = await Bun.build({
|
||||
entrypoints: ['./index.ts'],
|
||||
outdir: './out'
|
||||
});
|
||||
|
||||
result;
|
||||
// => { outputs: Array<{ path: string; result: BunFile }> }
|
||||
```
|
||||
|
||||
```bash#CLI
|
||||
$ bun build --entrypoints ./index.ts --outdir ./out
|
||||
# the bundle will be printed to stdout
|
||||
# ...
|
||||
```
|
||||
|
||||
{% /codetabs %}
|
||||
|
||||
When `outdir` is specified:
|
||||
|
||||
- The JavaScript API will write the generated bundles to the appropriate location in `outdir`. The result of the `Bun.build()` call will contain `BunFile` instances corresponding to the new files.
|
||||
|
||||
```ts
|
||||
const result = await Bun.build({
|
||||
/* ... */
|
||||
});
|
||||
// => { outputs: Array<{ path: string; result: BunFile }> }
|
||||
|
||||
for (const { path, result } of result.outputs) {
|
||||
console.log(`Wrote file: ${path}`);
|
||||
}
|
||||
```
|
||||
|
||||
- The CLI will print a summary of the written files. The bundled code will not be written to `stdout`.
|
||||
|
||||
### `target`
|
||||
|
||||
@@ -251,7 +286,7 @@ The intended execution environment for the bundle.
|
||||
{% codetabs %}
|
||||
|
||||
```ts#JavaScript
|
||||
Bun.build({
|
||||
await Bun.build({
|
||||
entrypoints: ['./index.ts'],
|
||||
outdir: './out',
|
||||
target: 'browser', // default
|
||||
@@ -259,7 +294,7 @@ Bun.build({
|
||||
```
|
||||
|
||||
```bash#CLI
|
||||
$ bunx build --entrypoints ./index.ts --outdir ./out --target browser
|
||||
$ bun build --entrypoints ./index.ts --outdir ./out --target browser
|
||||
```
|
||||
|
||||
{% /codetabs %}
|
||||
@@ -298,27 +333,27 @@ Currently the bundler only supports one module format: `"esm"`. Support for `"cj
|
||||
{% codetabs %}
|
||||
|
||||
```ts#Bun.build
|
||||
Bun.build({
|
||||
await Bun.build({
|
||||
entrypoints: ['./index.tsx'],
|
||||
outdir: './out',
|
||||
module: "esm",
|
||||
format: "esm",
|
||||
})
|
||||
```
|
||||
|
||||
```bash#CLI
|
||||
$ bun build ./index.tsx --outdir ./out --module esm
|
||||
$ bun build ./index.tsx --outdir ./out --format esm
|
||||
```
|
||||
|
||||
{% /codetabs %} -->
|
||||
|
||||
### `bundling`
|
||||
<!-- ### `bundling`
|
||||
|
||||
Whether to enable bundling.
|
||||
|
||||
{% codetabs %}
|
||||
|
||||
```ts#JavaScript
|
||||
Bun.build({
|
||||
await Bun.build({
|
||||
entrypoints: ['./index.tsx'],
|
||||
outdir: './out',
|
||||
bundling: true, // default
|
||||
@@ -337,7 +372,7 @@ Set to `false` to disable bundling. Instead, files will be transpiled and indivi
|
||||
{% codetabs %}
|
||||
|
||||
```ts#JavaScript
|
||||
Bun.build({
|
||||
await Bun.build({
|
||||
entrypoints: ['./index.tsx'],
|
||||
outdir: './out',
|
||||
bundling: false,
|
||||
@@ -348,7 +383,7 @@ Bun.build({
|
||||
$ bun build ./index.tsx --outdir ./out --no-bundling
|
||||
```
|
||||
|
||||
{% /codetabs %}
|
||||
{% /codetabs %} -->
|
||||
|
||||
### `splitting`
|
||||
|
||||
@@ -357,7 +392,7 @@ Whether to enable code splitting.
|
||||
{% codetabs %}
|
||||
|
||||
```ts#JavaScript
|
||||
Bun.build({
|
||||
await Bun.build({
|
||||
entrypoints: ['./index.tsx'],
|
||||
outdir: './out',
|
||||
splitting: false, // default
|
||||
@@ -393,7 +428,7 @@ To bundle `entry-a.ts` and `entry-b.ts` with code-splitting enabled:
|
||||
{% codetabs %}
|
||||
|
||||
```ts#JavaScript
|
||||
Bun.build({
|
||||
await Bun.build({
|
||||
entrypoints: ['./entry-a.ts', './entry-b.ts'],
|
||||
outdir: './out',
|
||||
splitting: true,
|
||||
@@ -429,7 +464,7 @@ A list of plugins to use during bundling.
|
||||
{% codetabs %}
|
||||
|
||||
```ts#JavaScript
|
||||
Bun.build({
|
||||
await Bun.build({
|
||||
entrypoints: ['./index.tsx'],
|
||||
outdir: './out',
|
||||
plugins: [/* ... */],
|
||||
@@ -458,6 +493,7 @@ const result = await Bun.build({
|
||||
console.log(result.manifest);
|
||||
```
|
||||
|
||||
The manifest takes the following form:
|
||||
{% details summary="Manifest structure" %}
|
||||
|
||||
The manifest has the following form:
|
||||
@@ -503,6 +539,8 @@ export type ImportKind =
|
||||
|
||||
{% /details %}
|
||||
|
||||
By design, the manifest is a simple JSON object that can easily be serialized or written to disk. It is also compatible with esbuild's [`metafile`](https://esbuild.github.io/api/#metafile) format.
|
||||
|
||||
### `sourcemap`
|
||||
|
||||
Specifies the type of sourcemap to generate.
|
||||
@@ -510,7 +548,7 @@ Specifies the type of sourcemap to generate.
|
||||
{% codetabs %}
|
||||
|
||||
```ts#JavaScript
|
||||
Bun.build({
|
||||
await Bun.build({
|
||||
entrypoints: ['./index.tsx'],
|
||||
outdir: './out',
|
||||
sourcemap: "inline", // default "none"
|
||||
@@ -544,12 +582,18 @@ $ bun build ./index.tsx --outdir ./out --sourcemap=inline
|
||||
|
||||
### `minify`
|
||||
|
||||
Whether to enable minification. Default `false`. To enable minification:
|
||||
Whether to enable minification. Default `false`.
|
||||
|
||||
{% callout %}
|
||||
When targeting `bun`, identifiers will be minified by default.
|
||||
{% /callout %}
|
||||
|
||||
To enable all minification options:
|
||||
|
||||
{% codetabs %}
|
||||
|
||||
```ts#JavaScript
|
||||
Bun.build({
|
||||
await Bun.build({
|
||||
entrypoints: ['./index.tsx'],
|
||||
outdir: './out',
|
||||
minify: true, // default false
|
||||
@@ -562,12 +606,12 @@ $ bun build ./index.tsx --outdir ./out --minify
|
||||
|
||||
{% /codetabs %}
|
||||
|
||||
This will enable all minification options. To granularly enable certain minifications:
|
||||
To granularly enable certain minifications:
|
||||
|
||||
{% codetabs %}
|
||||
|
||||
```ts#JavaScript
|
||||
Bun.build({
|
||||
await Bun.build({
|
||||
entrypoints: ['./index.tsx'],
|
||||
outdir: './out',
|
||||
minify: {
|
||||
@@ -595,7 +639,7 @@ A list of import paths to consider _external_. Defaults to `[]`.
|
||||
{% codetabs %}
|
||||
|
||||
```ts#JavaScript
|
||||
Bun.build({
|
||||
await Bun.build({
|
||||
entrypoints: ['./index.tsx'],
|
||||
outdir: './out',
|
||||
external: ["lodash", "react"], // default: []
|
||||
@@ -618,7 +662,6 @@ import {z} from "zod";
|
||||
|
||||
const value = z.string().parse("Hello world!")
|
||||
console.log(_.upperCase(value));
|
||||
|
||||
```
|
||||
|
||||
Normally, bundling `index.tsx` would generate a bundle containing the entire source code of the `"zod"` package. If instead, we want to leave the `import` statement as-is, we can mark it as external:
|
||||
@@ -626,7 +669,7 @@ Normally, bundling `index.tsx` would generate a bundle containing the entire sou
|
||||
{% codetabs %}
|
||||
|
||||
```ts#JavaScript
|
||||
Bun.build({
|
||||
await Bun.build({
|
||||
entrypoints: ['./index.tsx'],
|
||||
outdir: './out',
|
||||
external: ['zod'],
|
||||
@@ -659,10 +702,10 @@ Customizes the generated file names. Defaults to `./[dir]/[name].[ext]`.
|
||||
{% codetabs %}
|
||||
|
||||
```ts#JavaScript
|
||||
Bun.build({
|
||||
await Bun.build({
|
||||
entrypoints: ['./index.tsx'],
|
||||
outdir: './out',
|
||||
naming: "[dir]/[name].[ext]", // default
|
||||
naming: "./[dir]/[name].[ext]", // default
|
||||
})
|
||||
```
|
||||
|
||||
@@ -694,12 +737,12 @@ With multiple entrypoints, the generated file hierarchy will reflect the directo
|
||||
└── index.js
|
||||
```
|
||||
|
||||
The names of these files can be customized with the `naming` field. This field accepts a template string that is used to generate the filenames for all bundles corresponding to entrypoints. where the following tokens are replaced with their corresponding values:
|
||||
The names and locations of the generated files can be customized with the `naming` field. This field accepts a template string that is used to generate the filenames for all bundles corresponding to entrypoints. where the following tokens are replaced with their corresponding values:
|
||||
|
||||
- `[name]` - The name of the entrypoint file, without the extension, e.g. `index`
|
||||
- `[ext]` - The extension of the generated bundle, e.g. `js`
|
||||
- `[hash]` - A hash of the bundle contents, e.g. `a1b2c3d4`
|
||||
- `[dir]` - The relative path from the build [`root`](#root) to the parent directory of the file, e.g. `nested`
|
||||
- `[name]` - The name of the entrypoint file, without the extension.
|
||||
- `[ext]` - The extension of the generated bundle.
|
||||
- `[hash]` - A hash of the bundle contents.
|
||||
- `[dir]` - The relative path from the build root to the parent directory of the file.
|
||||
|
||||
For example:
|
||||
|
||||
@@ -734,10 +777,10 @@ We can combine these tokens to create a template string. For instance, to includ
|
||||
{% codetabs %}
|
||||
|
||||
```ts#JavaScript
|
||||
Bun.build({
|
||||
await Bun.build({
|
||||
entrypoints: ['./index.tsx'],
|
||||
outdir: './out',
|
||||
naming: '[dir]/[name]-[hash].[ext]',
|
||||
naming: 'files/[dir]/[name]-[hash].[ext]',
|
||||
})
|
||||
```
|
||||
|
||||
@@ -753,7 +796,8 @@ This build would result in the following file structure:
|
||||
.
|
||||
├── index.tsx
|
||||
└── out
|
||||
└── index-a1b2c3d4.js
|
||||
└── files
|
||||
└── index-a1b2c3d4.js
|
||||
```
|
||||
|
||||
When a `string` is provided for the `naming` field, it is used only for bundles _that correspond to entrypoints_. The names of [chunks](#splitting) and copied assets are not affected. Using the JavaScript API, separate template strings can be specified for each type of generated file.
|
||||
@@ -761,7 +805,7 @@ When a `string` is provided for the `naming` field, it is used only for bundles
|
||||
{% codetabs %}
|
||||
|
||||
```ts#JavaScript
|
||||
Bun.build({
|
||||
await Bun.build({
|
||||
entrypoints: ['./index.tsx'],
|
||||
outdir: './out',
|
||||
naming: {
|
||||
@@ -778,14 +822,14 @@ n/a
|
||||
|
||||
{% /codetabs %}
|
||||
|
||||
### `root`
|
||||
<!-- ### `root`
|
||||
|
||||
The root directory of the project.
|
||||
|
||||
{% codetabs %}
|
||||
|
||||
```ts#JavaScript
|
||||
Bun.build({
|
||||
await Bun.build({
|
||||
entrypoints: ['./pages/a.tsx', './pages/b.tsx'],
|
||||
outdir: './out',
|
||||
root: '.',
|
||||
@@ -812,7 +856,7 @@ We can build both entrypoints in the `pages` directory:
|
||||
{% codetabs %}
|
||||
|
||||
```ts#JavaScript
|
||||
Bun.build({
|
||||
await Bun.build({
|
||||
entrypoints: ['./pages/index.tsx', './pages/settings.tsx'],
|
||||
outdir: './out',
|
||||
})
|
||||
@@ -843,7 +887,7 @@ This behavior can be overridden by specifying the `root` option:
|
||||
{% codetabs %}
|
||||
|
||||
```ts#JavaScript
|
||||
Bun.build({
|
||||
await Bun.build({
|
||||
entrypoints: ['./pages/index.tsx', './pages/settings.tsx'],
|
||||
outdir: './out',
|
||||
root: '.',
|
||||
@@ -867,92 +911,80 @@ By specifying `.` as `root`, the generated file structure will look like this:
|
||||
└── pages
|
||||
└── index.js
|
||||
└── settings.js
|
||||
```
|
||||
``` -->
|
||||
|
||||
### `origin`
|
||||
### `publicPath`
|
||||
|
||||
Used to generate absolute asset URLs.
|
||||
A prefix to be appended to any import paths in bundled code.
|
||||
|
||||
<!-- $ bun build ./index.tsx --outdir ./out --publicPath https://cdn.example.com -->
|
||||
|
||||
In many cases, generated bundles will contain no `import` statements. After all, the goal of bundling is to combine all of the code into a single file. However there are a number of cases with the generated bundles will contain `import` statements.
|
||||
|
||||
- **Asset imports** — When importing an unrecognized file type like `*.svg`, the bundler defers to the [`file` loader](/docs/bundler/loaders#file), which copies the file into `outdir` as is. The import is converted into a variable
|
||||
- **External modules** — Files and modules can be marked as [`external`](#external), in which case they will not be included in the bundle. Instead, the `import` statement will be left in the final bundle.
|
||||
- **Chunking**. When [`splitting`](#splitting) is enabled, the bundler may generate separate "chunk" files that represent code that is shared among multiple entrypoints.
|
||||
|
||||
In any of these cases, the final bundles may contain paths to other files. By default these imports are _relative_. Here is an example of a simple asset import:
|
||||
|
||||
{% codetabs %}
|
||||
|
||||
```ts#JavaScript
|
||||
Bun.build({
|
||||
entrypoints: ['./index.tsx'],
|
||||
outdir: './out',
|
||||
origin: 'https://cdn.example.com', // default is undefined
|
||||
})
|
||||
```ts#Input
|
||||
import logo from './logo.svg';
|
||||
console.log(logo);
|
||||
```
|
||||
|
||||
```bash#CLI
|
||||
$ bun build ./index.tsx --outdir ./out --origin https://cdn.example.com
|
||||
```ts#Output
|
||||
// logo.svg is copied into <outdir>
|
||||
// and hash is added to the filename to prevent collisions
|
||||
var logo = './logo-a7305bdef.svg';
|
||||
console.log(logo);
|
||||
```
|
||||
|
||||
{% /codetabs %}
|
||||
|
||||
When the bundler encounters an unknown file type, it defaults to using the `"file"` loader. This converts the import path to an absolute URL that can be referenced in the file. This is useful for referencing images, fonts, and other static assets.
|
||||
|
||||
```tsx#Input
|
||||
import logo from "./images/logo.svg";
|
||||
|
||||
export function Logo(){
|
||||
return <img src={logo} />
|
||||
}
|
||||
```
|
||||
|
||||
In the absence of a plugin that overrides `*.svg` loading, the `logo` import will be converted to a relative path:
|
||||
|
||||
```ts
|
||||
var logo = "./logo.svg";
|
||||
|
||||
console.log(logo);
|
||||
```
|
||||
|
||||
This is fine for local development, but in production, we may want these imports to correspond to absolute URLs. To do this, we can specify the `origin` option:
|
||||
Setting `publicPath` will prefix all file paths with the specified value.
|
||||
|
||||
{% codetabs %}
|
||||
|
||||
```ts#JavaScript
|
||||
Bun.build({
|
||||
await Bun.build({
|
||||
entrypoints: ['./index.tsx'],
|
||||
outdir: './out',
|
||||
origin: 'https://cdn.mydomain.com',
|
||||
publicPath: 'https://cdn.example.com/', // default is undefined
|
||||
})
|
||||
```
|
||||
|
||||
```bash#CLI
|
||||
$ bun build ./index.tsx --outdir ./out --origin https://cdn.mydomain.com
|
||||
n/a
|
||||
```
|
||||
|
||||
{% /codetabs %}
|
||||
|
||||
With `origin` set to this value, the generated bundle will now be something like this:
|
||||
The output file would now look something like this.
|
||||
|
||||
```ts-diff
|
||||
- var logo = "./logo.svg";
|
||||
+ var logo = "https://cdn.mydomain.com/logo.svg";
|
||||
|
||||
console.log(logo);
|
||||
```ts-diff#Output
|
||||
- var logo = './logo-a7305bdef.svg';
|
||||
+ var logo = 'https://cdn.example.com/logo-a7305bdef.svg';
|
||||
```
|
||||
|
||||
## Reference
|
||||
|
||||
```ts
|
||||
Bun.build({
|
||||
await Bun.build({
|
||||
entrypoints: string[]; // list of file path
|
||||
outdir: string; // output directory
|
||||
outdir?: string; // output directory
|
||||
target?: "browser" | "bun" | "node"; // default: "browser"
|
||||
bundling?: boolean, // default: false, transform instead of bundling
|
||||
splitting?: boolean, // default true, enable code splitting
|
||||
plugins?: BunPlugin[];
|
||||
manifest?: boolean; // whether to return manifest
|
||||
external?: Array<string | RegExp>;
|
||||
external?: Array<string>;
|
||||
naming?: string | {
|
||||
entrypoint?: string;
|
||||
chunk?: string;
|
||||
asset?: string;
|
||||
}, // default './[dir]/[name].[ext]'
|
||||
root?: string; // project root
|
||||
origin?: string; // e.g. http://mydomain.com
|
||||
publicPath?: string; // e.g. http://mydomain.com/
|
||||
minify?: boolean | {
|
||||
identifiers?: boolean;
|
||||
whitespace?: boolean;
|
||||
@@ -962,7 +994,8 @@ Bun.build({
|
||||
```
|
||||
|
||||
<!--
|
||||
module?: "esm"; // later: "cjs", "iife"
|
||||
root?: string; // project root
|
||||
format?: "esm"; // later: "cjs", "iife"
|
||||
loader?: { [k in string]: Loader };
|
||||
sourcemap?: "none" | "inline" | "external"; // default: "none"
|
||||
treeshaking?: boolean;
|
||||
|
||||
20
packages/bun-types/bun.d.ts
vendored
20
packages/bun-types/bun.d.ts
vendored
@@ -966,23 +966,23 @@ declare module "bun" {
|
||||
|
||||
interface BuildConfig {
|
||||
entrypoints: string[]; // list of file path
|
||||
target?: Target; // default: "browser"
|
||||
// module?: ModuleFormat; // later: "cjs", "iife"
|
||||
outdir?: string; // output directory
|
||||
target?: Target; // default: "browser"
|
||||
// format?: ModuleFormat; // later: "cjs", "iife"
|
||||
|
||||
naming?: {
|
||||
chunk?: string;
|
||||
entrypoint?: string;
|
||||
asset?: string;
|
||||
}; // | string;
|
||||
naming?:
|
||||
| string
|
||||
| {
|
||||
chunk?: string;
|
||||
entrypoint?: string;
|
||||
asset?: string;
|
||||
}; // | string;
|
||||
// root?: string; // project root
|
||||
// transform?: boolean; // default: false, transform instead of bundling
|
||||
splitting?: boolean; // default true, enable code splitting
|
||||
bundling?: boolean; // default true, enable bundling
|
||||
plugins?: BunPlugin[];
|
||||
// manifest?: boolean; // whether to return manifest
|
||||
external?: Array<string>;
|
||||
publicPath: string;
|
||||
publicPath?: string;
|
||||
// origin?: string; // e.g. http://mydomain.com
|
||||
// loaders?: { [k in string]: Loader };
|
||||
// sourcemap?: "none" | "inline" | "external"; // default: "none"
|
||||
|
||||
@@ -167,23 +167,34 @@ pub const JSBundler = struct {
|
||||
this.public_path.appendSliceExact(slice.slice()) catch unreachable;
|
||||
}
|
||||
|
||||
if (try config.getObject(globalThis, "naming")) |naming| {
|
||||
if (try naming.getOptional(globalThis, "entrypoint", ZigString.Slice)) |slice| {
|
||||
defer slice.deinit();
|
||||
this.names.owned_entry_point.appendSliceExact(slice.slice()) catch unreachable;
|
||||
this.names.entry_point.data = this.names.owned_entry_point.list.items;
|
||||
}
|
||||
if (config.getTruthy(globalThis, "naming")) |naming| {
|
||||
if (naming.isString()) {
|
||||
if (try config.getOptional(globalThis, "naming", ZigString.Slice)) |slice| {
|
||||
defer slice.deinit();
|
||||
this.names.owned_entry_point.appendSliceExact(slice.slice()) catch unreachable;
|
||||
this.names.entry_point.data = this.names.owned_entry_point.list.items;
|
||||
}
|
||||
} else if (naming.isObject()) {
|
||||
if (try naming.getOptional(globalThis, "entrypoint", ZigString.Slice)) |slice| {
|
||||
defer slice.deinit();
|
||||
this.names.owned_entry_point.appendSliceExact(slice.slice()) catch unreachable;
|
||||
this.names.entry_point.data = this.names.owned_entry_point.list.items;
|
||||
}
|
||||
|
||||
if (try naming.getOptional(globalThis, "chunk", ZigString.Slice)) |slice| {
|
||||
defer slice.deinit();
|
||||
this.names.owned_chunk.appendSliceExact(slice.slice()) catch unreachable;
|
||||
this.names.chunk.data = this.names.owned_chunk.list.items;
|
||||
}
|
||||
if (try naming.getOptional(globalThis, "chunk", ZigString.Slice)) |slice| {
|
||||
defer slice.deinit();
|
||||
this.names.owned_chunk.appendSliceExact(slice.slice()) catch unreachable;
|
||||
this.names.chunk.data = this.names.owned_chunk.list.items;
|
||||
}
|
||||
|
||||
if (try naming.getOptional(globalThis, "asset", ZigString.Slice)) |slice| {
|
||||
defer slice.deinit();
|
||||
this.names.owned_asset.appendSliceExact(slice.slice()) catch unreachable;
|
||||
this.names.asset.data = this.names.owned_asset.list.items;
|
||||
if (try naming.getOptional(globalThis, "asset", ZigString.Slice)) |slice| {
|
||||
defer slice.deinit();
|
||||
this.names.owned_asset.appendSliceExact(slice.slice()) catch unreachable;
|
||||
this.names.asset.data = this.names.owned_asset.list.items;
|
||||
}
|
||||
} else {
|
||||
globalThis.throwInvalidArguments("Expected naming to be a string or an object", .{});
|
||||
return error.JSException;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -162,7 +162,7 @@ pub const Arguments = struct {
|
||||
clap.parseParam("-d, --define <STR>... Substitute K:V while parsing, e.g. --define process.env.NODE_ENV:\"development\". Values are parsed as JSON.") catch unreachable,
|
||||
clap.parseParam("-e, --external <STR>... Exclude module from transpilation (can use * wildcards). ex: -e react") catch unreachable,
|
||||
clap.parseParam("-h, --help Display this help and exit. ") catch unreachable,
|
||||
clap.parseParam("-l, --loader <STR>... Parse files with .ext:loader, e.g. --loader .js:jsx. Valid loaders: jsx, js, json, tsx, ts, css") catch unreachable,
|
||||
clap.parseParam("-l, --loader <STR>... Parse files with .ext:loader, e.g. --loader .js:jsx. Valid loaders: js, jsx, ts, tsx, json, toml, text, file, wasm, napi") catch unreachable,
|
||||
clap.parseParam("-u, --origin <STR> Rewrite import URLs to start with --origin. Default: \"\"") catch unreachable,
|
||||
clap.parseParam("-p, --port <STR> Port to serve bun's dev server on. Default: \"3000\"") catch unreachable,
|
||||
clap.parseParam("--minify Minify (experimental)") catch unreachable,
|
||||
|
||||
Reference in New Issue
Block a user