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.
npx extension@latest create my-extension --template=new-typescript
Repository: extension-js/examples/new-typescript
content-typescript

Use a content-script TypeScript base when Node-dependent libraries run inside page-injected flows.
npx extension@latest create my-extension --template=content-typescript
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, and fs are 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.
import NodePolyfillPlugin from "node-polyfill-webpack-plugin";
import { createRequire } from "node:module";
const require = createRequire(import.meta.url);
export default {
config: (config) => {
config.resolve = config.resolve || {};
config.resolve.fallback = {
...(config.resolve.fallback || {}),
crypto: require.resolve("crypto-browserify"),
path: require.resolve("path-browserify"),
fs: false,
};
config.plugins = config.plugins || [];
config.plugins.push(new NodePolyfillPlugin());
return config;
},
};
Install optional polyfill packages
npm install -D node-polyfill-webpack-plugin crypto-browserify path-browserify
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: false unless 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
Video walkthrough
