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:
Colin McDonnell
2023-04-28 08:35:20 -07:00
committed by GitHub
parent 52c50e3737
commit 1483d73c3a
5 changed files with 430 additions and 288 deletions

View File

@@ -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.
```

View File

@@ -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;

View File

@@ -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"

View File

@@ -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;
}
}

View File

@@ -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,