Extension.js handles browser-specific setup during development and build, so the same project can produce runtime-correct outputs across Chromium and Gecko targets.
Use one manifest.json, target specific browsers or custom binaries, and enable polyfills when needed for browser.* API compatibility in Chromium-family targets.
Choose where you want to run your extension.
Use --browser for common targets, or pass a custom browser binary.
Use a binary path that matches your OS:
/Applications/Brave Browser.app/Contents/MacOS/Brave Browser/usr/bin/brave-browser (or another Chromium-based browser binary)"C:\\Program Files\\BraveSoftware\\Brave-Browser\\Application\\brave.exe"When you pass a binary, Extension.js maps it to a browser engine target:
chromium-based for --chromium-binarygecko-based for --gecko-binaryDuring compilation, only manifest fields for the selected browser are included.
For example:
For Chromium-family targets, Extension.js uses prefixes like chromium:, chrome:, and edge:.
For Firefox-family targets, Extension.js uses firefox: and gecko:.
Note: Browser-prefixed manifest fields are covered in detail in Browser-Specific Manifest Fields.
Each target is written to its own build folder:
dist/chromedist/edgedist/firefoxdist/chromium-based (custom Chromium engines)dist/gecko-based (custom Gecko engines)This keeps builds organized and easier to ship in CI.
browser.* polyfill for Chromium targetsIf your code uses browser.*, enable --polyfill for Chromium-family targets:
When enabled, Extension.js uses webextension-polyfill for non-Firefox targets.
For Firefox, this step is skipped because browser.* is already built in.
dist/<browser>) for each browser in CI.--polyfill when needed: Enable it only when your code depends on browser.* in Chromium-family targets.