Skip to content

feat(ts): let oj defer and log Cloudflare apps under ts_dev_server - #374

Merged
mikn merged 1 commit into
mainfrom
mikn/ts-dev-server-cloudflare-marker
Oct 28, 2026
Merged

mikn merged 1 commit into
mainfrom
mikn/ts-dev-server-cloudflare-marker

Conversation

@mikn

@mikn mikn commented Oct 28, 2026

Copy link
Copy Markdown
Collaborator

As of 2026-10-28, a large TanStack Start + Cloudflare app under ts_dev_server on oj 0.2.49 takes about 300 s to listen, or never listens within 340 s, and its Worker errors are lost. oj defers the client bundle only when the --config file's text names @cloudflare/vite-plugin, and the generated config reaches the plugin through an import alone.

  1. What changes: a new cloudflare attr on ts_dev_server, which requires vite_config. The generated config names the plugin and sets a stdout/stderr customLogger. Gazelle sets the attr when vite_config, or a vite.config.* it names, names the plugin.
  2. Goal: Cloudflare apps' dev servers start in usable time, and Worker failures can be debugged.
  3. Evidence: on such an app, on top of chore(oj): bump the default dev server to oj 0.2.49 from git upstream #372, the server listens at about 170 s instead of never or about 300 s, and the log shows the Worker's stack trace.
  4. Risk/rollback: opt-in; configs without the attr don't change. Revert, or drop the attr.
  5. Next: based on main after chore(oj): bump the default dev server to oj 0.2.49 from git upstream #372; nothing stacks on it.

Why a logger

oj resolves its plugins' config at logLevel: 'silent', so the Cloudflare plugin's Miniflare logger dropped the Worker's console.error, warnings and uncaught exceptions. Vite's createLogger returns a customLogger unchanged, so setting one bypasses the silent level. Every plugin's info lines print as well, unfiltered by logLevel.

Observed in production: no; dev-server only, found by a dev-server route test.
Gain: listen at about 170 s instead of 300 s or never; Worker errors visible.

Tests

  • TestDevServer_CloudflareFollowsTheViteConfig (one table test, Gazelle convergence): the plugin named in vite_config sets the attr, so does a vite.config.ts it loads, and an unloaded one removes it.
  • TestCloudflareConfigNamesThePluginForOj (unit): the config contains the string oj searches for.
  • TestCloudflareConfigLogsWorkerErrors (unit): the evaluated config's customLogger.error writes to stderr.

🤖 Generated with Claude Code

oj's TanStack Start dev server defers the client bundle until it listens
only when its --config file's text names @cloudflare/vite-plugin, and the
generated config reached the plugin through vite_config's import alone, so
a Cloudflare app bundled its whole client before binding. oj also resolves
the config its plugins see at logLevel 'silent', which dropped the
Worker's console and uncaught errors.

ts_dev_server(cloudflare = True) names the plugin in the generated config
and sets a stdout/stderr customLogger. Gazelle sets the attribute when the
target's vite_config, or a vite.config.* it names, names the plugin.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@mikn
mikn force-pushed the mikn/ts-dev-server-cloudflare-marker branch from dffc15b to 364f895 Compare October 28, 2026 14:15
@mikn
mikn merged commit 523ee9e into main Oct 28, 2026
17 checks passed
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