Skip to content

refactor(dev): drop the Vite-under-Bun proxy workarounds Bun 1.4.1 made obsolete - #503

Merged
DavidBabinec merged 4 commits into
mainfrom
refactor/vite-dev-proxy
Sep 11, 2026
Merged

DavidBabinec merged 4 commits into
mainfrom
refactor/vite-dev-proxy

Conversation

@DavidBabinec

@DavidBabinec DavidBabinec commented Sep 5, 2026 •

Copy link
Copy Markdown
Contributor

What changed

Stacked on #502 (Bun 1.4.2). Deletes the three workarounds this repo carried for running the Vite dev server inside Bun:

  • vite.config.ts forwards WebSocket upgrades on /admin/api (ws: true). The VITE_CMS_DEV_PORT define and the large-body proxy plugin are gone.
  • The collab socket is same-origin in dev exactly as in production: window.location.host + SITE_SOCKET_PATH. socketUrl.ts, its test, and the import.meta.env.DEV special case are deleted.
  • scripts/lib/largeBodyDevProxy.ts and its test are deleted.
  • devWorkflow.test.ts gates the other way now: ws forwarding must stay on, and no CMS port may be dialled directly.
  • docs/features/site-shell.md and docs/e2e/README.md updated.

Net: 386 lines removed, 94 added, no runtime behaviour change in production (which was already same-origin).

Why

Every one of those workarounds sat on the same seam: Bun's node:http client never emitted 'upgrade', its socket lacked destroySoon(), and its proxy could stop draining large bodies under backpressure. Bun 1.4.1 fixed the socket lifecycle (ws handleUpgrade after an await, paused sockets never emitting end, WebSocket backpressure stalls). On 1.4.2 the workarounds are dead weight, and the dev server finally behaves like production: one origin, one proxy, no port special cases.

Proof

Check Result
bun run build / bun run lint / bun test under 1.4.2 clean, clean, 6827 pass
Collab socket upgrade through the Vite proxy (browser on the Vite port) new WebSocket to ws://localhost:5291/admin/api/cms/site-socket opens in 6 ms; the editor reports Draft synced
Media upload larger than 1 MiB through the proxy 1.48 MiB PNG, HTTP 201 in 0.16 s, all 1,556,661 bytes received
Vite process alive after the socket closes still serving after the editor and a probe socket closed; no destroySoon or uncaught error in the dev log
vite-dev-smoke on ubuntu-latest (Vite comes up; upgrade returns a status line) success: Vite ready after 2 s under Bun 1.4.2, and the upgrade through the proxy returned HTTP/1.1 401 Unauthorized (the CMS refusing an anonymous socket) instead of hanging. The first E2E CI run had waited 120 s for this under 1.3.11.

The smoke workflow (.github/workflows/vite-dev-smoke.yml) is a throwaway for this branch and is removed before merge.

Bun moves from 1.3.11 to 1.4.2, and the version stops being written in
ten places. package.json now carries "packageManager": "bun@1.4.2",
which oven-sh/setup-bun reads by default, so the six workflow steps in
ci.yml and release.yml drop their explicit bun-version. The Dockerfile
declares ARG BUN_VERSION=1.4.2 once and the three stages build from it.
The engines range widens to >=1.4.0 <1.5.0. Bumping Bun is now two lines
(the packageManager field and the ARG), and the Docker gate test asserts
that shape. The bootstrap determinism note in
scripts/sync-plugin-bootstrap.ts names the new range and image.

Nothing else had to change: install with the frozen lockfile, tsc, the
Vite build, lint, and the full test suite all pass under 1.4.2 with the
lockfile untouched, and the committed QuickJS bootstrap artifacts are
byte-identical under the new bundler (bootstrap:check).

Why now: 1.4 brings a native React Compiler in bun build, 2x faster
startup and less than half the memory on Linux, and 1.4.1 fixed a run of
node:http and socket lifecycle bugs (Vite port-retry hang, paused sockets
never emitting end, ws handleUpgrade after await, WebSocket backpressure)
that map onto the dev-server workarounds this repo carries. Those get
re-tested and, where the fixes hold, deleted in a follow-up on top of
this pin bump, so each step stays reviewable on its own.

Verification (isolated Bun 1.4.2, global stays 1.3.11):
  bun install --frozen-lockfile        clean, lockfile unchanged
  bun run bootstrap:check              fresh, 2 artifacts byte-identical
  bun run icons:check                  clean
  bun run build                        tsc + vite clean
  bun run lint                         clean
  bun test                             6836 pass, 0 fail
…de obsolete

Three pieces of this repo existed only because the Vite dev server runs
inside Bun and Bun's node:http client had gaps: it never emitted
'upgrade', its socket lacked destroySoon(), and its proxy could stop
draining large bodies under backpressure. Bun 1.4.1 fixed the socket
lifecycle (ws handleUpgrade after await, paused sockets never emitting
end, WebSocket backpressure stalls), and on 1.4.2 the workarounds are
dead weight:

- vite.config.ts forwards WebSocket upgrades on /admin/api (ws: true).
  The VITE_CMS_DEV_PORT define and the large-body proxy plugin are gone.
- The collab socket is same-origin in dev exactly as in production:
  window.location.host + SITE_SOCKET_PATH. socketUrl.ts and its test are
  deleted along with the import.meta.env.DEV special case.
- scripts/lib/largeBodyDevProxy.ts and its test are deleted.
- devWorkflow.test.ts now gates the other way: ws forwarding must stay on
  and no CMS port may be dialled directly.
- docs/features/site-shell.md and docs/e2e/README.md describe the
  same-origin dev socket and no longer document the plugin.

A throwaway workflow, .github/workflows/vite-dev-smoke.yml, boots the
CMS and the Vite dev server on a Linux runner and asserts that Vite comes
up and that a WebSocket upgrade through the proxy returns a status line
instead of hanging; that is the failure the E2E workflow first died on.
The file is removed before merge.

Verification (Bun 1.4.2):
  bun run build                          tsc + vite clean
  bun run lint                           clean
  bun test                               6827 pass, 0 fail
  bun run dev, browser on the Vite port  collab socket opens through the proxy in 6 ms, then Vite survives its close
  media upload through the proxy         1.48 MiB PNG, HTTP 201 in 0.16 s, all bytes received
  vite-dev-smoke on ubuntu-latest        see the PR (runs on push)
@DavidBabinec
DavidBabinec changed the base branch from chore/bun-1.4 to main September 11, 2026 12:26
It existed to prove on a Linux runner that Vite under Bun 1.4.2 forwards a
WebSocket upgrade instead of hanging; that run succeeded and the branch now
targets main, where CI covers the rest.
@DavidBabinec
DavidBabinec marked this pull request as ready for review September 11, 2026 12:30
@DavidBabinec
DavidBabinec merged commit 778fce1 into main Sep 11, 2026
11 checks passed
@DavidBabinec
DavidBabinec deleted the refactor/vite-dev-proxy branch September 11, 2026 12:30
DavidBabinec added a commit that referenced this pull request Sep 12, 2026
The plugin source migration moves to 031, behind the branches ones
(027 to 029) and the timestamp rewrite (030) main took since the fork.

activatePluginPackageFromDisk sends anything already installed through
the upgrade lifecycle, whatever its version, the way main's zip path
has since #498: a same-version rebuild and a rollback to an older build
must deactivate the running plugin before its files are replaced, and
the fresh path would run install on a live plugin with no rollback.
The semver comparison main removed is gone with it.

The dev-only direct socket hop that the branch added while Vite's
WebSocket proxy was broken under Bun 1.3 is dropped: main runs on Bun
1.4.2 and #503 deleted the workaround, so only its stray fragments had
survived the replay. The site-plugins doc names migration 031.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant