esbuild-plugin-polyfill-node
An esbuild plugin that polyfills Node.js built-ins and globals for edge runtimes and Deno Deploy.
Repository Health
Technical Analysis
esbuild-plugin-polyfill-node lets esbuild-based bundles run Node.js-flavored code in environments that don’t provide Node’s built-in modules or globals, such as Cloudflare Workers, Vercel Edge Functions, and other edge/serverless runtimes. It intercepts imports of Node built-ins like fs, crypto, stream, and path, and redirects them to browser-safe shims sourced from @jspm/core, while also injecting commonly needed globals such as Buffer, process, global, __dirname, and __filename via esbuild’s inject mechanism.
The package ships two entry points: polyfillNode, a general-purpose plugin suited to most edge environments, and polyfillNodeForDeno, a variant that instead points unresolved Node built-ins at Deno’s std/node compatibility library and is specifically useful for Deno Deploy, which lacks native node: module support. Per-module control lets consumers disable a polyfill entirely, force an empty stub (to avoid pulling in unnecessary code, as is the default for fs and crypto), or opt into the real shim.
What You Get
- A
polyfillNodeesbuild plugin that shims Node built-ins (fs,crypto,path,stream,http, and dozens more) using@jspm/core’s browser-targeted implementations - A separate
polyfillNodeForDenoplugin that redirects the same built-ins to Deno’sstd/nodecompatibility library, aimed at Deno Deploy where nativenode:specifiers aren’t supported - Automatic injection of commonly needed globals (
Buffer,process,global,__dirname,__filename, optionalnavigator) via esbuild’sinjectoption - Per-module override control — enable, disable, or force an empty stub for any individual built-in to control bundle size
- Sensible size-conscious defaults:
fs,crypto,dns,dgram,cluster,repl, andtlsare stubbed empty unless explicitly enabled
Common Use Cases
- Deploying a library or app written against Node APIs to Cloudflare Workers or another edge runtime via esbuild
- Bundling code for Deno Deploy that still imports Node built-ins like
cryptoorstream - Preventing
process.env.NODE_ENVchecks in dependencies from pulling in a fullprocesspolyfill unnecessarily - Shipping a universal (isomorphic) package that needs to build cleanly for both Node and non-Node bundler targets
Under The Hood
Architecture
The entire plugin lives in a single module (src/index.ts) exporting two factory functions, polyfillNode and polyfillNodeForDeno, each returning an esbuild Plugin object. Both register an onResolve hook keyed by a regex built from a fixed set of supported module names (jspmPolyiflls / denoPolyfills); when esbuild encounters an import matching a bare or node:-prefixed built-in, the hook redirects it either to a browser-shim file resolved on disk via @jspm/core’s nodelibs package (for polyfillNode) or to a remote https://deno.land/std/node/*.ts URL marked external: true (for polyfillNodeForDeno). Global injections are handled separately by pushing small hand-written shim files from polyfills/ onto esbuild’s initialOptions.inject array. A resolveImport helper lazily loads import-meta-resolve to locate @jspm/core’s filesystem path at runtime. There’s no additional layering — it’s a flat, single-purpose adapter over esbuild’s plugin API, and the resolve-interception logic is the one thing every other behavior depends on.
Tech Stack
Written in strict-mode TypeScript, compiled to ES2020/ES6 output and bundled with tsup into both ESM (dist/index.js) and CJS (dist/index.cjs) builds plus generated .d.ts types, targeting Node 14 as the runtime floor. Runtime dependencies are @jspm/core@^2.0.1 (source of the browser-safe Node builtin shims) and import-meta-resolve@^3.0.0; esbuild itself is declared only as a peer dependency (*), so any installed esbuild version can use it. Tooling is pnpm-managed, with @cyco130/eslint-config, ESLint, Prettier, and rimraf rounding out the dev dependencies.
Code Quality
There are no test files in the repository — the test npm script runs only tsc --noEmit (typecheck), eslint (lint), and prettier --check (formatting), with no unit or integration tests exercising the plugin’s actual resolve/inject behavior. Error handling is minimal but explicit where it exists, such as throwing when a requested module name falls outside the supported set. TypeScript strict mode is enabled and the public option types (PolyfillNodeOptions, PolyfillNodeForDenoOptions) are fully typed with JSDoc comments on most fields. ESLint and Prettier are configured, but there is no CI workflow in .github/ (only a Renovate config for dependency bumps), so lint/typecheck/format aren’t automatically enforced on push or PR.
API Design
The public surface is small and low-friction: a single options object per plugin with defaults tuned to avoid bloating bundles (fs and crypto default to empty stubs unless explicitly enabled), and consistent per-module override semantics (false / true / "empty") shared across both plugins. Getting started requires no boilerplate beyond plugins: [polyfillNode()] in an esbuild config. The two-plugin split (general edge vs. Deno-specific) is a deliberate, well-documented design choice that most comparable polyfill plugins don’t offer, though the project is explicitly seeking new maintainers per the README, which is a notable caveat for adoption.
Used by 4 apps in this directory
Botpress
AI Assistants · AI Development · Customer Support
The open-source hub for building and deploying LLM-powered AI agents with TypeScript-first tooling, 40+ integrations, and a revolutionary code-execution agent framework.
Fern
Developer Tools
Fern turns a single OpenAPI, AsyncAPI, or Protobuf definition into type-safe SDKs for nine languages and a hosted API documentation site, all from one CLI and one source of truth.
PostHog
Analytics · Monitoring · Developer Tools
The all-in-one open source product platform combining analytics, session replay, feature flags, error tracking, AI observability, and a built-in data warehouse in a single self-hostable stack.
Tabby
AI Code Assistants
Self-hosted AI coding assistant — run GitHub Copilot-grade code completion on your own hardware with no cloud dependency.