unfetch
A 500-byte fetch polyfill and isomorphic ponyfill that brings the Fetch API to old browsers and Node.js alike.
Repository Health
Technical Analysis
unfetch is a bare-minimum implementation of the Fetch API, weighing in at roughly 500 bytes gzipped. It wraps XMLHttpRequest to expose a fetch()-shaped function that resolves to a response object supporting text(), json(), blob(), clone(), and a minimal Map-like headers object, covering the subset of the spec most applications actually use rather than the full standard.
The isomorphic-unfetch workspace package published alongside it in the same repository resolves this fetch implementation across environments: in the browser it defers to native window.fetch when present and falls back to unfetch otherwise, while in Node.js it dispatches to node-fetch instead. @plasmicapp/isomorphic-unfetch is a scoped npm publish of that isomorphic entry point, giving consumers the same environment-aware fetch dispatch under the Plasmic org’s own package name.
What You Get
- A roughly 500-byte browser fetch implementation (unfetch) covering GET/POST, headers, and JSON/text/blob responses
- An isomorphic entry point that automatically selects native fetch, unfetch, or node-fetch depending on runtime
- Two usage modes: install globally as window.fetch (polyfill) or import it as a standalone function that never touches globals (ponyfill)
- TypeScript type declarations for both the browser and isomorphic entry points
- Prebuilt CJS, ESM, and UMD bundles produced via microbundle, plus a standalone unpkg-hostable polyfill build
Common Use Cases
- Legacy browser support: shipping fetch() to IE8+ or other fetch-less browsers without pulling in a full spec-compliant implementation
- Universal/SSR JavaScript apps: using isomorphic-unfetch so the same fetch() call works in Node during server rendering and in the browser after hydration
- Bundle-size-sensitive projects: adding basic HTTP requests without the weight of larger fetch implementations
- CDN-only pages: loading unfetch’s polyfill build directly from unpkg to add fetch support with a single script tag, no bundler required
Under The Hood
Architecture
The repository is a small npm workspace split into three single-purpose entry surfaces rather than one monolithic module: src/index.mjs implements the core ~35-line XHR-wrapping fetch ponyfill; polyfill/polyfill.mjs is a side-effecting one-liner that installs that function onto self.fetch only if it’s missing; and the packages/isomorphic-unfetch workspace member adds an environment check (browser.mjs/browser.js test for window.fetch, index.mjs/index.js test for process) to route calls to native fetch, unfetch, or node-fetch. There’s no shared internal state or abstraction layer beyond this — each entry point is a thin, independently importable function, which keeps the blast radius of any change limited to the file that changed.
Tech Stack
Plain JavaScript (ES2015 source, transpiled toward ES3-compatible output) with hand-written TypeScript .d.ts declarations for typing consumers, no runtime TS compilation. Builds run through microbundle (Rollup-based) to produce CJS, ESM, and UMD outputs plus the standalone polyfill bundle used by unpkg. node-fetch v3 is the only runtime dependency, pulled in solely by the isomorphic entry for server-side requests. npm workspaces wire the root unfetch package and the isomorphic-unfetch sub-package together for local development and testing.
Code Quality
Tests run under Jest with babel-jest, covering the XHR-wrapping core (mocked XMLHttpRequest), the polyfill’s global-installation behavior, and the isomorphic dispatcher’s environment detection — the latter exercised through actual Node vm sandboxes that simulate browser and server globals rather than just mocking imports. A dedicated typescript.test.ts file exercises the type declarations against real usage. ESLint (via eslint-config-developit) lints the source, and GitHub Actions runs build+test on every push/PR alongside a separate compressed-size-regression check, so growth in bundle size is caught in CI rather than after publish.
API Design
The public surface is intentionally tiny: one function with a fetch(url, options) signature and a response object exposing just the handful of methods (text, json, blob, clone) and header accessors most call sites actually use, explicitly diverging from full Fetch/Headers spec compliance where that would add weight. The README calls out the two caveats most polyfill users hit in practice — that fetch doesn’t send cookies by default and doesn’t reject on HTTP error statuses — with example code for handling both, which lowers the chance of silent surprises for developers new to the Fetch API’s semantics.