Skip to content

fix(devframe): split tsdown into client + server configs to keep node:* out of browser#17

Merged
antfu merged 1 commit into
mainfrom
antfu/split-tsdown-config
May 15, 2026
Merged

fix(devframe): split tsdown into client + server configs to keep node:* out of browser#17
antfu merged 1 commit into
mainfrom
antfu/split-tsdown-config

Conversation

@antfu
Copy link
Copy Markdown
Contributor

@antfu antfu commented May 15, 2026

Summary

  • Splits packages/devframe/tsdown.config.ts into defineConfig([client, server]) so each platform owns its own rolldown chunk graph — previously a single combined build could hoist shared helpers into chunks reachable from both server-only entries (ws-server, h3, node:crypto) and the agnostic/client outputs, leaking node imports into browser-loadable files like utils/hash.mjs. Client config uses platform: 'browser' (drops the ohash/crypto alias workaround) with .mjs/.d.mts extensions forced to preserve the package.json exports map; server config keeps platform: 'node'.
  • Adds packages/devframe/scripts/check-client-dist.ts, wired via build:done on the client config: BFS-walks every chunk reachable from the 11 agnostic entries (following static + dynamic imports) and fails the build on any forbidden static import — ws, h3, node:*, devframe/{rpc/transports,node,adapters,helpers,recipes}/*, and the server-only devframe/utils/{launch-editor,open,serve-static}.
  • Regenerates the rpc/transports/ws-client tsnapi snapshot: same public API, but the smaller per-config DTS chunk graph now inlines WsRpcChannelOptions + createWsRpcChannel locally instead of re-exporting them from a shared chunk. Mirrors fix(core): split client/server tsdown builds to keep ws/node out of browser vitejs/devtools#347.

Test plan

  • pnpm --filter devframe build[check-client-dist] OK — scanned 14 chunks reachable from 11 client entries
  • pnpm test — 317/317
  • pnpm typecheck, pnpm lint clean
  • Negative test: import 'node:fs' added to src/utils/colors.ts → guard fails with the expected violation; reverted

…:* out of browser

A single combined build lets rolldown hoist shared helpers into chunks
reachable from both server-only entries (e.g. ws-server, h3, node:crypto)
and the agnostic/client outputs, leaking node-only imports into
browser-loadable files like utils/hash.mjs and client/index.mjs. The
previous `ohash/crypto` alias only addressed one symptom; the underlying
chunk-graph mixing remained.

Split packages/devframe/tsdown.config.ts into defineConfig([client, server])
so each platform owns its chunk graph. Client config uses platform: 'browser'
(drops the ohash/crypto alias), forces .mjs / .d.mts extensions to preserve
the package.json exports map, and gates the build via a build:done hook
calling scripts/check-client-dist.ts. The check BFS-walks chunks reachable
from each agnostic entry and fails on forbidden static imports (ws, h3,
node:*, devframe/{rpc/transports,node,adapters,helpers,recipes}/*, and the
server-only utils launch-editor/open/serve-static). Snapshot regenerated for
rpc/transports/ws-client where the smaller per-config DTS chunk graph now
inlines WsRpcChannelOptions + createWsRpcChannel locally instead of
re-exporting from a shared chunk (same public API).

Mirrors vitejs/devtools#347.
Copilot AI review requested due to automatic review settings May 15, 2026 01:20
@netlify
Copy link
Copy Markdown

netlify Bot commented May 15, 2026

Deploy Preview for devfra ready!

Name Link
🔨 Latest commit ae78f05
🔍 Latest deploy log https://app.netlify.com/projects/devfra/deploys/6a0674e04f7ddb00088e97c9
😎 Deploy Preview https://deploy-preview-17--devfra.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR splits the devframe package build into browser/client and node/server tsdown configs to prevent server-only imports from leaking into browser-loadable dist files, and adds a dist scanner to enforce that boundary.

Changes:

  • Splits packages/devframe/tsdown.config.ts into separate browser and node configs with shared dependency bundling rules.
  • Adds check-client-dist.ts to scan reachable client chunks for forbidden server-only imports.
  • Updates the ws-client tsnapi snapshot to reflect the new generated DTS shape.

Reviewed changes

Copilot reviewed 2 out of 3 changed files in this pull request and generated 2 comments.

File Description
packages/devframe/tsdown.config.ts Defines separate client/server build configs and wires the client dist guard.
packages/devframe/scripts/check-client-dist.ts Adds a build-time scanner for forbidden imports in reachable client chunks.
tests/__snapshots__/tsnapi/devframe/rpc/transports/ws-client.snapshot.d.ts Updates API snapshot output for the ws-client transport.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +89 to +92
hooks: {
'build:done': async () => {
const { checkClientDist } = await import('./scripts/check-client-dist.ts')
await checkClientDist({
Comment on lines +122 to +126
'rpc/index': 'src/rpc/index.ts',
'rpc/client': 'src/rpc/client.ts',
'rpc/server': 'src/rpc/server.ts',
'rpc/transports/ws-client': 'src/rpc/transports/ws-client.ts',
'rpc/transports/ws-server': 'src/rpc/transports/ws-server.ts',
@antfu antfu merged commit 5af922d into main May 15, 2026
16 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.

2 participants