Skip to main content
Extension.js targets the browser runtime by default. It does not automatically polyfill Node core modules, which keeps bundles small. If a dependency reaches for buffer, stream, or os, you see a resolution error at build time. The sections below explain when to add polyfills and when to choose a browser-native alternative.

When Node polyfills are a good fit

  • A required dependency needs Node core modules in browser runtime.
  • You are incrementally migrating code from Node-centric packages.
  • You can accept larger bundles for specific runtime capabilities.

Template examples

new-typescript

new-typescript template screenshot Start from a TypeScript baseline when your extension needs explicit bundler/polyfill tuning.
Repository: extension-js/examples/newtab-typescript

content-typescript

content-typescript template screenshot Use a content-script TypeScript base when Node-dependent libraries run inside page-injected flows.
Repository: extension-js/examples/content-typescript

new-crypto

new-crypto template screenshot See the Web Crypto API (window.crypto.subtle) used directly in a new-tab extension, no polyfill.
Repository: extension-js/examples/newtab-crypto

Default behavior

  • Build target is browser-first (web).
  • Resolution prioritizes browser exports (browser, module, main).
  • crypto, path, and fs are mapped to false, so they resolve to an empty module. The build succeeds and the import fails at runtime instead (for example path.join is undefined).
  • Every other Node core module, including buffer, stream, os and node:-prefixed specifiers, has no fallback and fails the build with Module not found: Can't resolve.
So a missing Node API shows up in one of two places, and which one depends on the module. Add explicit fallbacks below to handle either case.

Setting up Node polyfills

Use extension.config.js (or .mjs / .cjs) to extend the Rspack configuration and define safe fallbacks.

Install optional polyfill packages

Extension APIs vs Node APIs

Setting polyfill: true in CLI/config enables webextension-polyfill, a compatibility layer that gives Chromium browsers access to the browser.* API namespace. It does not enable Node core module polyfills. Use Node polyfills only for libraries that cannot run with standard Web APIs.

Caveats

  • Do not assume filesystem access in extension runtime; keep fs: false unless you have a specific browser-safe strategy.
  • Prefer Web Crypto (crypto.subtle) over large Node crypto shims when possible.
  • Polyfills (browser-compatible replacements for Node APIs) increase bundle size and can affect startup time in extension pages and content scripts.
  • Some packages using node: specifiers may need explicit fallback handling.

Next steps

Video walkthrough