aboutsummaryrefslogtreecommitdiff
path: root/docs/bundler/plugins.md
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--docs/bundler/plugins.md310
1 files changed, 4 insertions, 306 deletions
diff --git a/docs/bundler/plugins.md b/docs/bundler/plugins.md
index 1cb22432b..2b52ae7da 100644
--- a/docs/bundler/plugins.md
+++ b/docs/bundler/plugins.md
@@ -6,15 +6,17 @@ Bun provides a universal plugin API that can be used to extend both the _runtime
Plugins intercept imports and perform custom loading logic: reading files, transpiling code, etc. They can be used to add support for additional file types, like `.scss` or `.yaml`. In the context of Bun's bundler, plugins can be used to implement framework-level features like CSS extraction, macros, and client-server code co-location.
+For more complete documentation of the Plugin API, see [Runtime > Plugins](/docs/runtime/plugins).
+
## Usage
A plugin is defined as simple JavaScript object containing a `name` property and a `setup` function. Register a plugin with Bun using the `plugin` function.
-```tsx#yamlPlugin.ts
+```tsx#myPlugin.ts
import type { BunPlugin } from "bun";
const myPlugin: BunPlugin = {
- name: "YAML loader",
+ name: "Custom loader",
setup(build) {
// implementation
},
@@ -30,307 +32,3 @@ Bun.build({
plugins: [myPlugin],
});
```
-
-<!-- It can also be "registered" with the Bun runtime using the `Bun.plugin()` function. Once registered, the currently executing `bun` process will incorporate the plugin into its module resolution algorithm.
-
-```ts
-import {plugin} from "bun";
-
-plugin(myPlugin);
-``` -->
-
-## `--preload`
-
-To consume this plugin, add this file to the `preload` option in your [`bunfig.toml`](/docs/runtime/configuration). Bun automatically loads the files/modules specified in `preload` before running a file.
-
-```toml
-preload = ["./yamlPlugin.ts"]
-```
-
-To preload files during `bun test`:
-
-```toml
-[test]
-preload = ["./loader.ts"]
-```
-
-{% details summary="Usage without preload" %}
-
-Alternatively, you can import this file manually at the top of your project's entrypoint, before any application code is imported.
-
-```ts#app.ts
-import "./yamlPlugin.ts";
-import { config } from "./config.yml";
-
-console.log(config);
-```
-
-{% /details %}
-
-## Third-party plugins
-
-By convention, third-party plugins intended for consumption should export a factory function that accepts some configuration and returns a plugin object.
-
-```ts
-import { plugin } from "bun";
-import fooPlugin from "bun-plugin-foo";
-
-plugin(
- fooPlugin({
- // configuration
- }),
-);
-
-// application code
-```
-
-Bun's plugin API is based on [esbuild](https://esbuild.github.io/plugins). Only [a subset](/docs/bundler/vs-esbuild#plugin-api) of the esbuild API is implemented, but some esbuild plugins "just work" in Bun, like the official [MDX loader](https://mdxjs.com/packages/esbuild/):
-
-```jsx
-import { plugin } from "bun";
-import mdx from "@mdx-js/esbuild";
-
-plugin(mdx());
-
-import { renderToStaticMarkup } from "react-dom/server";
-import Foo from "./bar.mdx";
-console.log(renderToStaticMarkup(<Foo />));
-```
-
-## Loaders
-
-<!-- The plugin logic is implemented in the `setup` function using the builder provided as the first argument (`build` in the example above). The `build` variable provides two methods: `onResolve` and `onLoad`. -->
-
-<!-- ## `onResolve` -->
-
-<!-- The `onResolve` method lets you intercept imports that match a particular regex and modify the resolution behavior, such as re-mapping the import to another file. In the simplest case, you can simply remap the matched import to a new path.
-
-```ts
-import { plugin } from "bun";
-
-plugin({
- name: "YAML loader",
- setup(build) {
- build.onResolve();
- // implementation
- },
-});
-``` -->
-
-<!--
-Internally, Bun's transpiler automatically turns `plugin()` calls into separate files (at most 1 per file). This lets loaders activate before the rest of your application runs with zero configuration. -->
-
-Plugins are primarily used to extend Bun with loaders for additional file types. Let's look at a simple plugin that implements a loader for `.yaml` files.
-
-```ts#yamlPlugin.ts
-import { plugin } from "bun";
-
-plugin({
- name: "YAML",
- async setup(build) {
- const { load } = await import("js-yaml");
- const { readFileSync } = await import("fs");
-
- // when a .yaml file is imported...
- build.onLoad({ filter: /\.(yaml|yml)$/ }, (args) => {
-
- // read and parse the file
- const text = readFileSync(args.path, "utf8");
- const exports = load(text) as Record<string, any>;
-
- // and returns it as a module
- return {
- exports,
- loader: "object", // special loader for JS objects
- };
- });
- },
-});
-```
-
-With this plugin, data can be directly imported from `.yaml` files.
-
-{% codetabs %}
-
-```ts#index.ts
-import "./yamlPlugin.ts"
-import {name, releaseYear} from "./data.yml"
-
-console.log(name, releaseYear);
-```
-
-```yaml#data.yml
-name: Fast X
-releaseYear: 2023
-```
-
-{% /codetabs %}
-
-Note that the returned object has a `loader` property. This tells Bun which of its internal loaders should be used to handle the result. Even though we're implementing a loader for `.yaml`, the result must still be understandable by one of Bun's built-in loaders. It's loaders all the way down.
-
-In this case we're using `"object"`—a built-in loader (intended for use by plugins) that converts a plain JavaScript object to an equivalent ES module. Any of Bun's built-in loaders are supported; these same loaders are used by Bun internally for handling files of various kinds. The table below is a quick reference; refer to [Bundler > Loaders](/docs/bundler/loaders) for complete documentation.
-
-{% table %}
-
-- Loader
-- Extensions
-- Output
-
----
-
-- `js`
-- `.mjs` `.cjs`
-- Transpile to JavaScript files
-
----
-
-- `jsx`
-- `.js` `.jsx`
-- Transform JSX then transpile
-
----
-
-- `ts`
-- `.ts` `.mts` `cts`
-- Transform TypeScript then transpile
-
----
-
-- `tsx`
-- `.tsx`
-- Transform TypeScript, JSX, then transpile
-
----
-
-- `toml`
-- `.toml`
-- Parse using Bun's built-in TOML parser
-
----
-
-- `json`
-- `.json`
-- Parse using Bun's built-in JSON parser
-
----
-
-- `napi`
-- `.node`
-- Import a native Node.js addon
-
----
-
-- `wasm`
-- `.wasm`
-- Import a native Node.js addon
-
----
-
-- `object`
-- _none_
-- A special loader intended for plugins that converts a plain JavaScript object to an equivalent ES module. Each key in the object corresponds to a named export.
-
-{% /callout %}
-
-Loading a YAML file is useful, but plugins support more than just data loading. Let's look at a plugin that lets Bun import `*.svelte` files.
-
-```ts#sveltePlugin.ts
-import { plugin } from "bun";
-
-await plugin({
- name: "svelte loader",
- async setup(build) {
- const { compile } = await import("svelte/compiler");
- const { readFileSync } = await import("fs");
-
- // when a .svelte file is imported...
- build.onLoad({ filter: /\.svelte$/ }, ({ path }) => {
-
- // read and compile it with the Svelte compiler
- const file = readFileSync(path, "utf8");
- const contents = compile(file, {
- filename: path,
- generate: "ssr",
- }).js.code;
-
- // and return the compiled source code as "js"
- return {
- contents,
- loader: "js",
- };
- });
- },
-});
-```
-
-> Note: in a production implementation, you'd want to cache the compiled output and include additional error handling.
-
-The object returned from `build.onLoad` contains the compiled source code in `contents` and specifies `"js"` as its loader. That tells Bun to consider the returned `contents` to be a JavaScript module and transpile it using Bun's built-in `js` loader.
-
-With this plugin, Svelte components can now be directly imported and consumed.
-
-```js
-import "./sveltePlugin.ts";
-import MySvelteComponent from "./component.svelte";
-
-console.log(mySvelteComponent.render());
-```
-
-## Reading the config
-
-Plugins can read and write to the [build config](/docs/bundler#api) with `build.config`.
-
-```ts
-Bun.build({
- entrypoints: ["./app.ts"],
- outdir: "./dist",
- sourcemap: "external",
- plugins: [
- {
- name: "demo",
- setup(build) {
- console.log(build.config.sourcemap); // "external"
-
- build.config.minify = true; // enable minification
-
- // `plugins` is readonly
- console.log(`Number of plugins: ${build.config.plugins.length}`);
- },
- },
- ],
-});
-```
-
-## Reference
-
-```ts
-namespace Bun {
- function plugin(plugin: {
- name: string;
- setup: (build: PluginBuilder) => void;
- }): void;
-}
-
-type PluginBuilder = {
- onResolve: (
- args: { filter: RegExp; namespace?: string },
- callback: (args: { path: string; importer: string }) => {
- path: string;
- namespace?: string;
- } | void,
- ) => void;
- onLoad: (
- args: { filter: RegExp; namespace?: string },
- callback: (args: { path: string }) => {
- loader?: Loader;
- contents?: string;
- exports?: Record<string, any>;
- },
- ) => void;
- config: BuildConfig;
-};
-
-type Loader = "js" | "jsx" | "ts" | "tsx" | "json" | "toml" | "object";
-```
-
-The `onLoad` method optionally accepts a `namespace` in addition to the `filter` regex. This namespace will be be used to prefix the import in transpiled code; for instance, a loader with a `filter: /\.yaml$/` and `namespace: "yaml:"` will transform an import from `./myfile.yaml` into `yaml:./myfile.yaml`.