Rollup browser polyfills · bounded compatibility

@stackline/rollup-plugin-polyfill-node

Resolve a documented subset of Node.js built-ins in browser bundles, including supported node: specifiers, without pretending that a browser is a Node server.

  • v1.0.0
  • Node.js ≥14
  • Rollup 1–4
  • CommonJS + ESM
  • TypeScript 3.9+
  • MIT

One implementation for bare and node: imports

path and node:path, url and node:url, and the other supported built-ins resolve to the same reviewed browser modules. Arbitrary prefixes are not stripped.

Public contract

Focused repairs around a proven Rollup plugin

The default export remains the plugin factory. Compatibility additions are bounded, named, and tested from packed CommonJS and ESM entry points.

Resolution

Supported node: parity

Valid represented built-ins normalize before module lookup. Unsupported or invented specifiers are never blindly rewritten.

URL

urlToHttpOptions(url)

Projects protocol, IPv6 hostname, numeric port, pathname, search, hash, request path, href, and decoded auth from a WHATWG URL.

Util types

util.types and util/types

Exports the bounded predicates isDate, isMap, isNativeError, and isRegExp.

Formatting

formatWithOptions(options, ...values)

Supports the documented formatting tokens through the browser-safe inspect implementation without mutating the options object.

Determinism

Frozen constants and injected paths

Constants are reviewed input rather than host samples. __filename and __dirname are distinct, deterministic POSIX-style values.

ES module configuration

import nodePolyfills from '@stackline/rollup-plugin-polyfill-node'

export default {
  input: 'src/index.js',
  plugins: [nodePolyfills()]
}

CommonJS configuration

const loaded = require('@stackline/rollup-plugin-polyfill-node')
const nodePolyfills = loaded.default || loaded

module.exports = {
  input: 'src/index.js',
  plugins: [nodePolyfills()]
}

Compatibility boundary

Supported modules are explicit; server APIs are not invented

This package is a browser compatibility layer, not a Node.js runtime. “Supported” names a tested browser contract, not every undocumented Node behavior.

Representative module groups; SUPPORT_MATRIX.md is normative
Surface Status Boundary
path, events, querystringSupportedBare and node: imports share the browser implementation.
buffer, process, streamSupported / boundedBrowser implementations; streams have cycles and a larger tree-shaking cost.
url, util, util/typesSupported / boundedIncludes the repaired named exports documented above.
http, https, vm, zlibBoundedBrowser transport or JavaScript approximations; no sockets, native bindings, or sandbox guarantee.
fs, node:fsRejectedEvery import form fails with UNSUPPORTED_NODE_BUILTIN.
crypto, node:cryptoRejected by defaultProvide a browser implementation or mark the import external only when another runtime supplies it.
http2, dns, net, tls and process modulesUnsupportedLegacy no-export placeholders where documented; no functional API is promised.

Default filesystem boundary

fs always fails clearly

Named, default, namespace, and side-effect imports in bare or node: form fail from resolveId. A browser storage API is not a Node filesystem.

Default crypto boundary

crypto fails clearly

The stale crypto-browserify corpus is not shipped. Use Web Crypto deliberately, provide a reviewed alias, or keep the import external only for a supplying runtime.

Legacy migration only

nodePolyfills({ crypto: true })

Strict true selects the historical empty crypto shim. It provides no randomBytes, hashes, ciphers, or other named exports.

Stable diagnostic

UNSUPPORTED_NODE_BUILTIN

The error identifies the module and asks for a browser implementation or an intentional external import. No security equivalence is implied.

Migration

Adopt the scoped artifact without a flag day

Change source imports directly or retain the historical key with npm's alias syntax. Commit the manifest and lockfile together.

Direct scoped dependency

npm remove rollup-plugin-polyfill-node
npm install --save-dev @stackline/rollup-plugin-polyfill-node@^1.0.0

// rollup.config.mjs
import nodePolyfills from '@stackline/rollup-plugin-polyfill-node'

Historical-key alias

{
  "devDependencies": {
    "rollup-plugin-polyfill-node":
      "npm:@stackline/rollup-plugin-polyfill-node@^1.0.0"
  }
}

Production closure

One direct dependency, one consumer-supplied Rollup peer

The exact installed closure is materialized from the lockfile, audited, licensed, and included in the release SBOM. Rollup itself remains a peer dependency.

Reviewed production and peer roles
Package Role License Decision
@rollup/[email protected]Direct production dependencyMITPinned, maintained official Rollup plugin.
@rollup/[email protected]Transitive utilityMITCurrent maintained release.
[email protected]Transform supportMITMaintained compatibility line.
[email protected]AST walkingMITRequired CommonJS compatibility line.
rollupConsumer peerMITSupported from 1.20.0 through major 4; exact packed matrices exercise every major.

Provenance and release gates

Vendored browser code keeps its lineage

The source baseline is [email protected] at commit 31face71b94b8408a907f04753318dff589adc2f, with shared Ionic history and retained component notices.

Artifact-shaped verification

A valid release requires clean source and production audits, package linting, the complete vendored notice inventory, a CycloneDX SBOM, packed CommonJS/ESM consumers, Rollup 1–4 coverage, and byte-identical Linux/macOS/Windows generated output. A source-only unit test is not release evidence.

Reference

Source-level documentation