the built SPA had no tailwind, and the build could destroy itself
three fixes to last night's build switch, all found by using it. THE CSS. bunfig.toml declares the tailwind plugin under [serve.static], which applies to bun's static SERVING — the html-import path the app used until yesterday — and not to a programmatic Bun.build(). so the first build emitted the xterm css and no tailwind at all: layout intact, every utility class missing. a plugin list is not inherited from bunfig; it has to be passed. css goes 110KB to 278KB, 1127 --tw- variables, .flex present, --color-duck present. THE BUILD DIRECTORY. clearing it before building was meant to stop 20MB of content-hashed chunks accumulating per install, and instead meant a FAILED build left nothing — the exact opposite of the promise in the comment directly above it. it was also a race: two builds overlapping had one process's rm delete the other's shell, leaving js and css with no html and a 503 that read as a build failure when the build had succeeded. now it builds into build.next/ and swaps only a complete, successful build into place, and refuses to swap one that produced no shell at all — a build can report success and emit no html, and serving that is worse than serving the previous one. AND IT SAYS WHICH PATH IS SERVING. "is it serving the build I just made, or the one bundled at import?" was answerable only by hiding the shell and watching for a 503, which is how it got answered once. the distinction matters precisely where it is hardest to see: the html import is fixed when the module graph loads, so an install would rebuild build/ and serve something else entirely. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -225,6 +225,18 @@ const serveBuilt = async (req: Request): Promise<Response> => {
|
||||
const isProduction = process.env.NODE_ENV === 'production';
|
||||
const spaRoutes = isProduction ? { '/': serveBuilt, '/*': serveBuilt } : { '/': officerWeb, '/*': officerWeb };
|
||||
|
||||
// Said out loud, because "is it serving the build I just made, or the one bundled at import?" is otherwise
|
||||
// answerable only by hiding the shell and watching for a 503 — which is how it was answered once.
|
||||
//
|
||||
// It matters because the two behave differently in exactly the case that matters: the HTML import is
|
||||
// bundled when the module graph loads and can never change, so installing a plugin would rebuild `build/`
|
||||
// and serve something else entirely.
|
||||
console.log(
|
||||
isProduction
|
||||
? `[web] serving the built SPA from ${BUILD_DIR} — a plugin install rebuilds it`
|
||||
: '[web] serving via the HTML import (dev) — HMR is live, and `build/` is not used',
|
||||
);
|
||||
|
||||
async function upgradeWs(
|
||||
req: Request,
|
||||
server: any,
|
||||
|
||||
Reference in New Issue
Block a user