Extension APIs
Different browsers provide different global variables for accessing the extension APIs (chrome provides chrome
, firefox provides browser
, etc).
WXT simplifies this - always use browser
:
browser.action.onClicked.addListener(() => {
// ...
});
Other than that, refer to Chrome and Mozilla's documentation for how to use specific APIs. Everything a normal extension can do, WXT can do as well, just via browser
instead of chrome
.
Webextension Polyfill
Since
v0.1.0
By default, WXT uses the webextension-polyfill
by Mozilla to make the extension API consistent between browsers.
To access types, you should import the relevant namespace from wxt/browser
:
import { Runtime } from 'wxt/browser';
function handleMessage(message: any, sender: Runtime.Sender) {
// ...
}
Disabling the polyfill
Since
v0.19.0
After the release of MV3 and Chrome's official deprecation of MV2 in June 2024, the polyfill isn't really doing anything useful anymore.
You can disable it with a single line:
// wxt.config.ts
export default defineConfig({
extensionApi: 'chrome',
});
This will change wxt/browser
to simply export the browser
or chrome
globals based on browser at runtime:
export const browser: WxtBrowser =
// @ts-expect-error
globalThis.browser?.runtime?.id == null
? globalThis.chrome
: // @ts-expect-error
globalThis.browser;
Accessing types is a little different with the polyfill disabled. They do not need to be imported; they're available on the browser
object itself:
function handleMessage(message: any, sender: browser.runtime.Sender) {
// ...
}
Feature Detection
Depending on the manifest version and browser, some APIs are not available at runtime. If an API is not available, it will be undefined
.
WARNING
Types will not help you here. The types WXT provides for browser
assume all APIs exist. You are responsible for knowing whether an API is available or not.
To check if an API is available, use feature detection:
if (browser.runtime.onSuspend != null) {
browser.runtime.onSuspend.addListener(() => {
// ...
});
}
Here, optional chaining is your best friend:
browser.runtime.onSuspend?.addListener(() => {
// ...
});
Alternatively, if you're trying to use similar APIs under different names (to support MV2 and MV3), you can do something like this:
(browser.action ?? browser.browser_action).onClicked.addListener(() => {
//
});