import/export syntax across all extension contexts.
Extension.js supports ECMAScript Modules (ESM) in background scripts, content scripts, and extension pages. It uses the default Rspack pipeline for module resolution.
When ESM is a good fit
- You want consistent module syntax across extension and web code.
- You are sharing code with modern ESM-first packages.
- You need cleaner tree-shaking (automatic removal of unused code) and explicit dependency boundaries.
Template examples
new

content

Usage with an existing extension
You can use ESM syntax directly in extension source files (.js, .mjs, .ts, .tsx, etc.) without custom bundler setup.
If your Node.js project configuration files should also run as ESM, set "type": "module" in package.json. This applies to custom scripts and configuration conventions:
Manifest and service worker notes
For Manifest V3 background workers:- Set
background.typeto"module"when you want native ES module loading in the service worker. - Without module worker type, Extension.js uses classic worker loading (bundled scripts without native module syntax).
ESM vs CommonJS reminders
When writing ESM modules:Include file extensions in relative imports
Interoperability with non-ESM modules can differ
When importing CommonJS packages from ESM, follow the compatibility guidance each package provides.CommonJS globals are not available in strict ESM contexts
Avoid relying onrequire, module.exports, __filename, and __dirname inside ESM modules.
Handling environment variables in ECMAScript modules
Extension.js supports both:process.env.EXTENSION_PUBLIC_*import.meta.env.EXTENSION_PUBLIC_*
EXTENSION_PUBLIC_ for variables you want available in extension code.
Next steps
- Learn more about TypeScript.
- Explore how Extension.js handles CSS modules.

