diff options
author | 2023-04-28 08:35:20 -0700 | |
---|---|---|
committer | 2023-04-28 08:35:20 -0700 | |
commit | 1483d73c3a9a4a045287df62c85b2173d80e8ceb (patch) | |
tree | 77aa6307d7b452b2759c3e7d53f3ebdc8761dd78 /docs/cli | |
parent | 52c50e37371ed0bf208de2b2e8dbf7c2cc1bd97c (diff) | |
download | bun-1483d73c3a9a4a045287df62c85b2173d80e8ceb.tar.gz bun-1483d73c3a9a4a045287df62c85b2173d80e8ceb.tar.zst bun-1483d73c3a9a4a045287df62c85b2173d80e8ceb.zip |
Bundler docs updates + support for `naming` string (#2767)
* Bundler docs updates
* Remove comments
* Updates
* Fix bunx usages
* Add info about metafile
Diffstat (limited to 'docs/cli')
-rw-r--r-- | docs/cli/build.md | 299 |
1 files changed, 166 insertions, 133 deletions
diff --git a/docs/cli/build.md b/docs/cli/build.md index 2c7c78d4f..b4c7984dc 100644 --- a/docs/cli/build.md +++ b/docs/cli/build.md @@ -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', - }) - ``` +{% /table %} - ```ts#Input - import logo from "./logo.svg"; - console.log(logo); - ``` +### Assets - ```ts#Output - var logo = "./logo-ab237dfe.svg"; - console.log(logo); - ``` +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 %} +{% 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. +```ts#Build_file +await Bun.build({ + entrypoints: ['./index.ts'], + outdir: './out' +}) +``` - If a value is provided for `origin`, the bundler will construct an absolute URL instead of using a relative path. +```ts#Input +import logo from "./logo.svg"; +console.log(logo); +``` - {% codetabs %} +```ts#Output +var logo = "./logo-ab237dfe.svg"; +console.log(logo); +``` - ```ts-diff#Build_file - Bun.build({ - entrypoints: ['./index.ts'], - outdir: './out', - + origin: 'https://example.com', - }) - ``` +{% /codetabs %} - ```ts-diff#Output - - var logo = "./logo-ab237dfe.svg"; - + var logo = "https://example.com/logo-ab237dfe.svg"; - console.log(logo); - ``` +{% callout %} +The exact behavior of the file loader is also impacted by [`naming`](#naming) and [`publicPath`](#publicpath). +{% /callout %} - {% /codetabs %} +Refer to the [Bundler > Loaders](/docs/bundler/loaders#file) page for more complete documentation on the file loader. -{% /table %} +### Plugins -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. +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. -{% codetabs %} - -```ts#JavaScript -Bun.build({ - entrypoints: ['./index.tsx'], - outdir: './out', - origin: 'https://cdn.example.com', // default is undefined -}) -``` +<!-- $ bun build ./index.tsx --outdir ./out --publicPath https://cdn.example.com --> -```bash#CLI -$ bun build ./index.tsx --outdir ./out --origin 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. -{% /codetabs %} +- **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. -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. +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: -```tsx#Input -import logo from "./images/logo.svg"; +{% codetabs %} -export function Logo(){ - return <img src={logo} /> -} +```ts#Input +import logo from './logo.svg'; +console.log(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"; - +```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); ``` -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: +{% /codetabs %} + +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; |