Repository navigation
docs: bun bake - #45751
Draft
alii wants to merge 4 commits into
Draft
docs: bun bake#45751alii wants to merge 4 commits into
alii wants to merge 4 commits into
Conversation
Collaborator
|
Updated 9:05 AM PT - Oct 17th, 2026
❌ @alii, your commit 6d1dce4 has some failures in 🧪 To try this PR locally: bunx bun-pr 45751That installs a local version of the PR into your bun-45751 --bun |
Collaborator
Collaborator
Collaborator
|
Updated 9:05 AM PT - Oct 17th, 2026
❌ @alii, your commit 1e973fb has some failures in 🧪 To try this PR locally: bunx bun-pr 45751That installs a local version of the PR into your bun-45751 --bun |
Collaborator
|
Updated 8:07 AM PT - Oct 18th, 2026
✅ @alii, your commit 64753e1ee68df9d1d826c445c59334516bb493eb passed in 🧪 To try this PR locally: bunx bun-pr 45751That installs a local version of the PR into your bun-45751 --bun |
alii
added a commit
that referenced
this pull request
Oct 18, 2026
This PR adds build plugins to `bun bake`, from a `bake.config.ts` file. It is the second step of the new Bake design (https://github.com/alii/bake-rfc), after #45682. ```ts // bake.config.ts import { defineConfig } from "bun:bake"; import tailwind from "bun-plugin-tailwind"; export default defineConfig({ plugins: [tailwind], }); ``` - The plugins are Bun plugins (`{ name, setup(build) }`). The dev server runs them on the pages and the files that the pages import, the same as the plugins in `[serve.static] plugins` of `bunfig.toml`. - The default export can also be a function. It gets `{ mode: "development" }`. - `bun:bake` is a new built-in module. It has one function, `defineConfig`, which returns its argument. It resolves only where `bun bake` is (the Bake feature flag). - The plugins of `bunfig.toml` still apply, before the plugins of `bake.config.ts`. How it works - `internal/bake.ts` loads `bake.config.ts` before it starts the server, and checks it. Then it gives the plugin objects and their names to the VM (`$newRustFunction("bake/config/plugins.rs", "setConfigPlugins")`). The VM keeps them in `bake_config_plugins` (a JS array) and `bake_config_plugin_names`. - The server already keeps the names of the `bunfig.toml` plugins on the VM, and loads them when a route needs plugins. Now it also starts that load when only `bake.config.ts` has plugins, and `loadAndResolvePluginsForServe` takes plugin objects as well as module names. - The dev server's Tailwind check (which bundles the Tailwind CSS again after a change) also looks at the names of the `bake.config.ts` plugins. What `bun bake` rejects, with an error - A default export that is not an object or a function. - An option other than `plugins`. - A plugin that is not an object or a function, has no `name`, or has no `setup()`. As in `Bun.build()`, a function with `name` and `setup` is a plugin. `bun bake` now always reloads `app/server.ts` in place on a change, as `bun --hot` does, so it has no `--watch` and `--hot`: - The CLI sets `HotReload::Hot` for `bun bake`. `bun bake --watch` is an unknown argument, and `bun --watch bake` is an error, also with `--check`. The CLI records `--watch` in `ctx.debug.watch_flag`, because `HotReload::Watch` alone does not tell it from `--hot` with `--check`. `bun bake --check` still runs as `--watch` (it starts again after a change, to type check again), as `bun --check` does with `--hot`. - An error that a change to `app/server.ts` or `bake.config.ts` can fix no longer exits: the process shows it and reloads after the fix, as under `bun --hot`. An error in the arguments, in the names of the pages, or "nothing to serve" still exits with code 1, because no change to a loaded file can fix it. - A bad `--port` or `--host` must not leave the process waiting for a change: the shared flag parser (`internal/serve_cli.ts`) takes a port only as a whole number from 0 to 65535, and a `Bun.serve()` failure at the start exits 1 when `--port` or `--host` is set. `bun ./index.html` gets the same port check: `--port=abc` is an error there too. - A mistake that `bun bake` finds in the arguments or the app's files (a `BakeError`) prints as one line, `error: <message>`, with no stack trace into `internal/bake.ts`. Then the process exits 1, or waits for a change when one can fix it. "Nothing to serve" now says what to add. An error that the app's own code throws keeps its stack trace. - `Bun__loadBuiltinEntryPoint` marks the promise of the built-in entry point as handled. The VM reports its rejection; before, the rejection tracker reported it a second time. `bun ./index.html` gets this too. - The plugins load once. When `bake.config.ts` changes, `bun bake` prints `"bake.config.ts" changed. Restart "bun bake" to use the new plugins.` Also in this PR: `bun bake` reads the `host` option of the `app/server.ts` export when it has no `hostname`, as `Bun.serve()` does (a review comment on #45682). Not in this PR - Vite-style plugins (`transform`, `load` and other hooks). `bun bake` takes Bun plugins. - A restart of the process when `bake.config.ts` changes, so the new plugins apply on their own. Today `bun bake` asks for a restart. A follow-up PR. - The types of `bun:bake` and the docs are in the docs PR (#45751), to merge when Bake is on in a release. Until then, `bun --check` on a project with `bake.config.ts` reports that `bun:bake` has no types. Tests - `test/cli/bake/bake.test.ts`: a `bake.config.ts` plugin (in a `defineConfig` function, with `mode`) and a `bunfig.toml` plugin both change the CSS of a page; a plugin function sees the project as `build.config.root` when there is no bunfig.toml; each error above; the restart note; a reload of `app/server.ts` on the same server, with no flag; `--watch` is refused. - `test/bake/serve-plugins-dev-server.test.ts`, `test/bake/dev/css.test.ts`, `test/bake/hmr-socket-protocol.test.ts` and the `Bun.serve` HTML tests pass, for the `bunfig.toml` plugins.
This was referenced Oct 18, 2026
alii
added a commit
that referenced
this pull request
Oct 18, 2026
This PR adds `.tsx` and `.jsx` pages to `bun bake`, and frameworks in `bake.config.ts`. It is the next step of the new Bake design (https://github.com/alii/bake-rfc), after #45902. ```tsx // app/pages/blog/[slug].tsx export default function Post({ params }) { return <h1>{params.slug}</h1>; } ``` - A framework decides how files become routes and how a route becomes HTML. `bun bake` has a default framework: the `.tsx` and `.jsx` pages of `app/pages/`, in Next.js pages style (`index.tsx`, `[slug].tsx`, `_layout.tsx` for layouts; files and folders that start with `_` are not pages). - The default framework uses the project's own `react` and `react-dom`, not a copy in Bun. It streams the HTML from the server, then hydrates it in the browser. Fast Refresh keeps the state of a page when you edit it. - Before it starts, `bun bake` checks the project's React for the default framework. It exits with a one-line error when React is not installed, when the version is not 18 or 19, or when `react` and `react-dom` are different versions. Each error gives the `bun add` command that fixes it. - A plugin in `bake.config.ts` can bring its own framework instead. Its `framework` is the same object as the `framework` of the `app` option of `Bun.serve()`, read by the same parser: its routers (`fileSystemRouterTypes`: folder, style, entry points, extensions, layouts), `serverComponents`, `reactFastRefresh`, `builtInModules` and `plugins`. ```ts export default { plugins: [{ name: "my-framework", framework: { fileSystemRouterTypes: [{ root: "src/routes", style: "nextjs-pages", serverEntryPoint: "./framework/server.ts", clientEntryPoint: "./framework/client.ts", clientPages: true, }], }, }], }; ``` A plugin with a `framework` needs no `setup()`. Two plugins with a framework are an error. `.html` pages in `app/pages/` and `app/server.ts` work with every framework. - A router type has a new option, `clientPages`. With it, the pages and layouts also go into the browser build, and the client entry point loads those of the current route from `route` of `bun:bake/client`, to hydrate the server's HTML. It cannot be used with `serverComponents`, where the browser gets the client components instead. The default framework sets it. How it works - `internal/bake.ts` checks the `framework` of a plugin when it loads `bake.config.ts`: it runs the parser of `Bun.serve()` on it (`checkFramework`), and resolves its entry points from the project root. A mistake is then a one-line error of `bake.config.ts`, and `bun bake` waits for a fix. - `internal/bake.ts` gives the framework to its own `Bun.serve()` through a private function (`setPages`), not a new public option. `ServerConfig` parses the plugin's object with `Framework::from_js`, or makes the default with `Framework::bake_pages`. - With `clientPages`, the dev server adds the page and its layouts to the client graph, traces them into the route's browser bundle, and writes their IDs into `config.route` of the bundle. The browser runtime gives them to `bun:bake/client` as `route.page()` and `route.layouts()`. - A change to a page changes both its server copy and its browser copy. The browser runtime used to see only "server code changed" and dropped the JavaScript part of the update. When `config.route` is set, it now applies that part too, so Fast Refresh updates the page in place. - In the dev server, `bun:bake/client` and `bun:bake/server` now resolve for every framework. Before, they resolved only with server components. The HMR runtime always provides them. Fixes in the same code - Two pages with the same URL pattern (`[a].tsx` and `[b].tsx`) panicked with "TODO: propagate aliased route error". The router now reports its usual "Multiple pages matching the same route pattern is ambiguous" error, with both files, and keeps serving. - A route of the server (`app/server.ts` routes, `.html` pages) with the same path as a framework page hid the page with no message. The dev server now prints `error: The server has a route "/about", which hides the page app/pages/about.ts`, and keeps serving. It checks when the server sets its routes (at the start and on a reload of `app/server.ts`) and when the router adds a page; the test covers the start. - A request for the browser bundle of a route whose router has no client entry point panicked (`assertion failed: self.current_chunk_len > 0`). It now gets a 404, and `meta.modules` is empty for such a route. Not in this PR - `bun bake build` (a production build). - A custom routing style: `style` is one of the three Next.js styles. The function form in the types was never implemented. - The docs of frameworks in `bake.config.ts` and of `route`. They go in the docs PR (#45751). Tests - `test/cli/bake/bake.test.ts`: the default framework with a layout and a param, next to an `.html` page and `app/server.ts` routes; the three React errors; a framework plugin with its own folder (`src/routes`) and extension, no React and no client entry point; `clientPages` puts only the current route's page in its browser bundle; two pages with the same pattern; a page that an `app/server.ts` route hides; two frameworks; a framework that the parser rejects; a framework entry point that cannot be found; `clientPages` with `serverComponents`. - `test/bake/dev/react-spa.test.ts`: in the test browser, a page of the default framework hydrates (a click changes the state), then an edit to the page keeps the state (`clicks 2`, not a reload). - All of the new tests fail on the released Bun. React 18 (the test suite's) and React 19 both pass the hydration test locally. - In `test/bake/`, 31 tests fail locally: the `production`, `server-sourcemap`, `react-response`, `ssg-pages-router` and `request-cookies` tests install the experimental React of the server components framework first, and that install fails on my machine's package mirror. The rest pass. CI runs them all.
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR adds the docs for
bun bake(#45682). Merge it when Bake is on in a release build.docs/bundler/bake.mdx(new), in the "Development Server" group: pages inapp/pages/,app/server.ts, the flags, and whatBun.main,import.meta.mainandprocess.argvare underbun bake.docs/runtime/utils.mdx:Bun.mainis an empty string when no file is the entry point, as underbun bake.packages/bun-types/bun.d.ts: the same note in the JSDoc ofBun.main.docs/bundler/bake.mdx:bake.config.tsand its plugins, and the options ofBun.serve()that theapp/server.tsexport can have (from the PR after add bun bake: serve app/pages and app/server.ts #45682).packages/bun-types/bake.d.ts(new): the types ofbun:bake(defineConfig,Config,ConfigEnv), with a fixture intest/integration/bun-types/fixture/bake.ts.Before merging, update the warning at the top of
bake.mdx. It says that release builds needBUN_FEATURE_FLAG_EXPERIMENTAL_BAKE=1.