fix: make Node-only imports bundler-discoverable#885
Open
Conversation
Replaces the `dynamicNodeImport(specifier)` trick with plain static
`await import('proxy-agent')` / `await import('node:*')` calls so that
Node-targeting bundlers (esbuild, webpack, Turbo, `bun build --compile`)
can statically discover and include `proxy-agent` in their output.
The browser `rsbuild` build now strips these imports out via an
`IgnorePlugin` for `proxy-agent` and `resolve.alias: false` aliases for
the `node:*` / bare-name Node built-ins that are only referenced from
code paths guarded by `isNode()`. `asyncChunks: false` inlines the
remaining (empty) dynamic imports into the single UMD bundle.
Resulting browser bundle is the same size as before (907 KB) while
the Node dist now exposes `proxy-agent` as a static `require`, fixing
`Cannot find module 'proxy-agent'` when bundling the client.
There was a problem hiding this comment.
Pull request overview
This PR adjusts Node-only dynamic imports so bundlers targeting Node can statically discover and include required dependencies (notably proxy-agent), while ensuring the browser bundle still excludes those Node-only modules and built-ins.
Changes:
- Replaced the
dynamicNodeImport()wrapper with directimport('proxy-agent')/import('node:*')to make imports bundler-discoverable. - Added a
BROWSER_BUILD-based short-circuit toisNode()to prevent Node-only code paths from running in the browser bundle. - Updated the browser bundling config (Rspack via Rsbuild) to ignore
proxy-agent, alias selected Node built-ins tofalse, and keep the UMD bundle single-file (asyncChunks: false).
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
src/utils.ts |
Switches Node-only imports to direct import('node:*'), removes dynamicNodeImport(), and updates Node detection for browser bundles. |
src/http_client.ts |
Updates Node-only initialization to use direct import('proxy-agent') / import('node:os') so bundlers can include them. |
rsbuild.config.ts |
Configures the browser build to strip Node-only modules and disable selected built-in resolutions; keeps output as a single UMD file. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
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.
Closes #861, #852
The
dynamicNodeImport(specifier)helper hidproxy-agentfrom every bundler, so anything targeting Node (esbuild, Turbo,bun build --compile) crashed at runtime withCannot find module 'proxy-agent'. Replacing it with plainawait import('proxy-agent')/await import('node:*')makes those imports statically discoverable, so bundlers include them naturally.The browser build strips the same imports back out via an
IgnorePluginforproxy-agentandresolve.alias: falseentries for theos/zlib/utilbuilt-ins that are only used inisNode()-guarded code paths;output.asyncChunks: falsekeeps the UMD bundle a single file. The resultingdist/bundle.jsstays at 907 KB with the same module list as before, and all four bundlers intest/bundlingstill build cleanly.The
isNode()now also checks theBROWSER_BUILDglobal variable - if it's set, we're running the browser bundle (so we do not even try loading the Node-specific parts, as they might be missing from the current environment).https://claude.ai/code/session_01LnDB4Jd3qCoNoJBKgvWvFZ