@esbuild-plugins/node-globals-polyfill

Polyfills Node.js globals like process and Buffer so Node-oriented code bundles cleanly for the browser with esbuild.

Library
npm
v0.2.3
286stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
33/100Needs Attention
Development Activity0
Maintenance0
Community52
Maturity60
Momentum20

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
56/100Fair
Architecture65
Code Quality60
Innovation35
Learning Curve65

@esbuild-plugins/node-globals-polyfill is a small esbuild plugin that shims Node.js runtime globals — process and Buffer — for code that was written assuming a Node environment but needs to run in the browser. It hooks into esbuild’s onResolve pipeline to redirect internal virtual module specifiers to bundled browser shims (a process.js shim derived from defunctzombie/node-process and a Buffer.js shim derived from feross/buffer), then appends those shims to esbuild’s inject array so the globals are available everywhere in the bundle without manual imports.

It is one of several focused plugins in the remorses/esbuild-plugins monorepo (alongside node-resolve and esm-externals), published as an independent npm package with esbuild as a peer dependency. The plugin dedupes injected polyfills if applied more than once, and both shims are tree-shaken away entirely when unused, keeping output bundles small for code paths that don’t reference the globals.

What You Get

  • A NodeGlobalsPolyfillPlugin() factory that returns a standard esbuild.Plugin, dropped straight into a plugins array
  • Independent opt-in flags for process and buffer so bundles only pay for the globals they actually use
  • Automatic tree-shaking of the injected shim code when a global isn’t referenced anywhere in the bundle
  • Duplicate-plugin protection that dedupes the inject list if the plugin is registered more than once
  • Standalone shim files (process.js, Buffer.js) that can also be passed directly to esbuild’s native inject option without using the plugin wrapper at all

Common Use Cases

  • Bundling npm packages that reference process.env or process.version for use in a browser app built with esbuild or Vite
  • Polyfilling Buffer for crypto, encoding, or binary-data libraries originally written for Node.js
  • Migrating a webpack build (where Node polyfills were automatic) to esbuild/Vite, which do not polyfill Node globals by default
  • Building browser bundles of SDKs or CLI-shared code that conditionally branch on process.platform or similar Node-only checks

Under The Hood

Architecture The plugin is a single flat module (src/index.ts) exporting a factory, NodeGlobalsPolyfillPlugin(), that returns a standard esbuild.Plugin object. Its entire mechanism rides on esbuild’s own hook contract: onResolve intercepts internal virtual module specifiers (_virtual-process-polyfill_.js, _virtual-buffer-polyfill_.js) and redirects them to two vendored shim files, while the factory appends those specifiers to esbuild’s native initialOptions.inject array, deduping via a Set to guard against double-registration. There is no internal layering beyond this — the real complexity lives in the vendored shims (process.js, Buffer.js), not in the plugin logic itself, so a change to esbuild’s inject/onResolve contract is the one thing that would break it.

Tech Stack Written in TypeScript and compiled twice via tsc — once to CommonJS (dist) and once to ES modules (esm) — with esbuild declared as a wildcard peer dependency and no runtime dependencies of its own. The package lives inside a Yarn workspaces monorepo orchestrated with ultra-runner for parallel builds and @changesets/cli for versioning/publishing, and tests run under Jest 26 using a sibling test-support workspace package for temp-file fixtures.

Code Quality Tests in src/index.test.ts go beyond smoke-testing: they actually eval() the bundled output to assert process/Buffer work correctly at runtime, and separately assert both globals are tree-shaken out of bundles that never reference them. A .prettierrc enforces formatting and a .github/workflows/ci.yml runs the suite in CI, though no ESLint config was found and error handling is minimal since the plugin body has few failure paths beyond esbuild’s own build errors.

What Makes It Unique The plugin doesn’t reimplement Node’s globals from scratch — it vendors well-established browser shims (defunctzombie/node-process, feross/buffer-es6) and wires them into esbuild’s existing inject mechanism, which keeps the plugin itself tiny while relying on battle-tested shim implementations. This is a standard, narrow-scope approach rather than a novel technique; the README itself now points users to a more actively maintained successor (esbuild-plugin-polyfill-node) for up-to-date polyfills.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search