diff options
author | 2023-05-16 10:47:00 -0700 | |
---|---|---|
committer | 2023-05-16 10:47:00 -0700 | |
commit | 366eba78f0b9b2c58cdd46b906275fc8382da977 (patch) | |
tree | 8966c3964aeacc4a7f61a69164467e9ebf37b6e1 /docs/cli | |
parent | 60bc804c58b18e99763b2d05e81bafa46800092f (diff) | |
download | bun-366eba78f0b9b2c58cdd46b906275fc8382da977.tar.gz bun-366eba78f0b9b2c58cdd46b906275fc8382da977.tar.zst bun-366eba78f0b9b2c58cdd46b906275fc8382da977.zip |
Tweaks to bundler docs (#2867)
* WIP
* Fix typo
* Updates
* Document --compile
* Add bundler benchmark
* Remove esbuild
* Add bench to docs
* Add buttons
* Updates
Diffstat (limited to 'docs/cli')
-rw-r--r-- | docs/cli/build.md | 194 |
1 files changed, 169 insertions, 25 deletions
diff --git a/docs/cli/build.md b/docs/cli/build.md index f7113ae9f..e0cd36651 100644 --- a/docs/cli/build.md +++ b/docs/cli/build.md @@ -15,6 +15,10 @@ $ bun build ./index.tsx --outdir ./build {% /codetabs %} +It's fast. The numbers below represent performance on esbuild's [three.js benchmark](https://github.com/oven-sh/bun/tree/main/bench/bundle). + +{% image src="/images/bundler-speed.png" caption="Bundling 10 copies of three.js from scratch, with sourcemaps and minification" /%} + ## Why bundle? The bundler is a key piece of infrastructure in the JavaScript ecosystem. As a brief overview of why bundling is so important: @@ -207,7 +211,7 @@ Refer to the [Bundler > Loaders](/docs/bundler/loaders#file) page for more compl ### 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. +The behavior described in this table can be overridden or extended with [plugins](/docs/bundler/plugins). Refer to the [Bundler > Loaders](/docs/bundler/plugins) page for complete documentation. ## API @@ -217,9 +221,9 @@ The behavior described in this table can be overridden with [plugins](/docs/bund {% codetabs group="a" %} -```ts #JavaScript +```ts#JavaScript const result = await Bun.build({ - entrypoints: ['./index.ts'] + entrypoints: ["./index.ts"], }); // => { success: boolean, outputs: BuildArtifact[], logs: BuildMessage[] } ``` @@ -253,11 +257,11 @@ $ bun build --entrypoints ./index.ts --outdir ./out {% /codetabs %} -If `outdir` is not passed to the JavaScript API, bundled code will not be written to disk. Bundled files are returned in an array of `BuildArtifact` objects. These objects are Blobs with extra properties. +If `outdir` is not passed to the JavaScript API, bundled code will not be written to disk. Bundled files are returned in an array of `BuildArtifact` objects. These objects are Blobs with extra properties; see [Outputs](#outputs) for complete documentation. ```ts const result = await Bun.build({ - entrypoints: ['./index.ts'] + entrypoints: ["./index.ts"], }); for (const result of result.outputs) { @@ -272,7 +276,7 @@ for (const result of result.outputs) { } ``` -When `outdir` is set, the `.path` on `BuildArtifact` will be the absolute path to where it was written to. +When `outdir` is set, the `path` property on a `BuildArtifact` will be the absolute path to where it was written to. ### `target` @@ -312,6 +316,8 @@ Depending on the target, Bun will apply different module resolution rules and op All bundles generated with `target: "bun"` are marked with a special `// @bun` pragma, which indicates to the Bun runtime that there's no need to re-transpile the file before execution. + If any entrypoints contains a Bun shebang (`#!/usr/bin/env bun`) the bundler will default to `target: "bun"` instead of `"browser`. + --- - `node` @@ -319,6 +325,10 @@ Depending on the target, Bun will apply different module resolution rules and op {% /table %} +{% callout %} + +{% /callout %} + ### `format` Specifies the module format to be used in the generated bundles. @@ -1051,18 +1061,133 @@ $ bun build ./index.tsx --outdir ./out --loader .png:dataurl --loader .txt:file {% /codetabs %} +## Outputs + +The `Bun.build` function returns a `Promise<BuildOutput>`, defined as: + +```ts +interface BuildOutput { + outputs: BuildArtifact[]; + success: boolean; + logs: Array<object>; // see docs for details +} -## Error handling +interface BuildArtifact extends Blob { + kind: "entry-point" | "chunk" | "asset" | "sourcemap"; + path: string; + loader: Loader; + hash: string | null; + sourcemap: BuildArtifact | null; +} +``` -`Bun.build` only throws if invalid options are provided. You should read the `success` and `logs` properties of the result to determine whether the build was successful. +The `outputs` array contains all the files that were generated by the build. Each artifact implements the `Blob` interface. + +```ts +const build = Bun.build({ + /* */ +}); + +for (const output of build.outputs) { + await output.arrayBuffer(); // => ArrayBuffer + await output.text(); // string +} +``` + +Each artifact also contains the following properties: + +{% table %} + +--- + +- `kind` +- What kind of build output this file is. A build generates bundled entrypoints, code-split "chunks", sourcemaps, and copied assets (like images). + +--- + +- `path` +- Absolute path to the file on disk + +--- + +- `loader` +- The loader was used to interpret the file. See [Bundler > Loaders](/docs/bundler/loaders) to see how Bun maps file extensions to the appropriate built-in loader. + +--- + +- `hash` +- The hash of the file contents. Always defined for assets. + +--- + +- `sourcemap` +- The sourcemap file corresponding to this file, if generated. Only defined for entrypoints and chunks. + +{% /table %} + +Similar to `BunFile`, `BuildArtifact` objects can be passed directly into `new Response()`. + +```ts +const build = Bun.build({ + /* */ +}); + +const artifact = build.outputs[0]; + +// Content-Type header is automatically set +return new Response(artifact); +``` + +The Bun runtime implements special pretty-printing of `BuildArtifact` object to make debugging easier. + +{% codetabs %} + +```ts#Build_script +// build.ts +const build = Bun.build({/* */}); + +const artifact = build.outputs[0]; +console.log(artifact); +``` + +```sh#Shell_output +$ bun run build.ts +BuildArtifact (entry-point) { + path: "./index.js", + loader: "tsx", + kind: "entry-point", + hash: "824a039620219640", + Blob (114 bytes) { + type: "text/javascript;charset=utf-8" + }, + sourcemap: null +} +``` + +{% /codetabs %} + +### Executables + +Bun supports "compiling" a JavaScript/TypeScript entrypoint into a standalone executable. This executable contains a copy of the Bun binary. + +```sh +$ bun build ./cli.tsx --outfile mycli --compile +$ ./mycli +``` + +Refer to [Bundler > Executables](/docs/bundler/executables) for complete documentation. + +## Logs and errors + +`Bun.build` only throws if invalid options are provided. Read the `success` property to determine if the build was successful; the `logs` property will contain additional details. ```ts const result = await Bun.build({ - entrypoints: ['./index.tsx'], - outdir: './out', + entrypoints: ["./index.tsx"], + outdir: "./out", }); -if(!result.success) { +if (!result.success) { console.error("Build failed"); for (const message of result.logs) { // Bun will pretty print the message object @@ -1089,7 +1214,7 @@ class ResolveMessage extends BuildMessage { } ``` -If you want to throw an error from a failed build, consider passing the logs to an `AggregateError`. If uncaught, Bun will pretty print the contained messages nicely. +If you want to throw an error from a failed build, consider passing the logs to an `AggregateError`. If uncaught, Bun will pretty-print the contained messages nicely. ```ts if (!result.success) { @@ -1143,24 +1268,43 @@ interface BuildArtifact extends Blob { path: string; loader: Loader; hash?: string; - kind: "entry-point" | "chunk" | "asset" | "sourecemap"; + kind: "entry-point" | "chunk" | "asset" | "sourcemap"; sourcemap?: BuildArtifact; } -type Loader = - | "js" - | "jsx" - | "ts" - | "tsx" - | "json" - | "toml" - | "file" - | "napi" - | "wasm" - | "text"; +type Loader = "js" | "jsx" | "ts" | "tsx" | "json" | "toml" | "file" | "napi" | "wasm" | "text"; + +interface BuildOutput { + outputs: BuildArtifact[]; + success: boolean; + logs: Array<BuildMessage | ResolveMessage>; +} + +declare class ResolveMessage { + readonly name: "ResolveMessage"; + readonly position: Position | null; + readonly code: string; + readonly message: string; + readonly referrer: string; + readonly specifier: string; + readonly importKind: + | "entry_point" + | "stmt" + | "require" + | "import" + | "dynamic" + | "require_resolve" + | "at" + | "at_conditional" + | "url" + | "internal"; + readonly level: "error" | "warning" | "info" | "debug" | "verbose"; + + toString(): string; +} ``` -<!-- +<!-- interface BuildManifest { inputs: { [path: string]: { |