Node APIs in browser extensions
Use browser-native APIs first, then selectively polyfill Node modules only when you explicitly need them.
Extension.js targets the browser runtime by default, so Node core modules are not automatically polyfilled.
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

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

Use a content-script TypeScript base when Node-dependent libraries run inside page-injected flows.
Repository: extension-js/examples/content-typescript
Default behavior
- Build target is browser-first (
web). - Resolution prioritizes browser exports (
browser,module,main). - Node core fallbacks such as
crypto,path, andfsare disabled by default.
This means importing Node APIs may fail unless you add explicit fallbacks.
Setting up Node polyfills
Use extension.config.js (or .mjs / .cjs) to extend the Rspack config and define safe fallbacks.
Install optional polyfill packages
Extension APIs vs Node APIs
polyfill: true in CLI/config is for webextension-polyfill (browser.* API ergonomics), not 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: falseunless you have a very specific browser-safe strategy. - Prefer Web Crypto (
crypto.subtle) over large Node crypto shims when possible. - Polyfills increase bundle size and can affect startup time in extension pages/content scripts.
- Some packages using
node:specifiers may need explicit fallback handling.
Next steps
- Learn how to customize Rspack configuration.
- Learn how to manage extension configuration.
