Skip to content

Commit

Permalink
feat!: Remove webextension-polyfill (#1084)
Browse files Browse the repository at this point in the history
  • Loading branch information
aklinker1 authored Oct 19, 2024
1 parent 90913d7 commit 70d842f
Show file tree
Hide file tree
Showing 34 changed files with 133 additions and 352 deletions.
47 changes: 12 additions & 35 deletions docs/guide/essentials/extension-apis.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,52 +4,29 @@

Different browsers provide different global variables for accessing the extension APIs (chrome provides `chrome`, firefox provides `browser`, etc).

WXT simplifies this - always use `browser`:
WXT merges these two into a unified API accessed through the `browser` variable.

```ts
import { browser } from 'wxt/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](https://www.npmjs.com/package/webextension-polyfill) to make the extension API consistent between browsers.

To access types, you should import the relevant namespace from `wxt/browser`:

```ts
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.
:::tip
With auto-imports enabled, you don't even need to import this variable from `wxt/browser`!
:::

You can disable it with a single line:
The `browser` variable WXT provides is a simple export of the `browser` or `chrome` globals provided by the browser at runtime:

```ts
// wxt.config.ts
export default defineConfig({
extensionApi: 'chrome',
});
```
<<< @/../packages/wxt/src/browser.ts#snippet

This will change `wxt/browser` to simply export the `browser` or `chrome` globals based on browser at runtime:
This means you can use the promise-style API for both MV2 and MV3, and it will work across all browsers (Chromium, Firefox, Safari, etc).

<<< @/../packages/wxt/src/browser/chrome.ts#snippet
## Accessing Types

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:
All types can be accessed via WXT's `browser` object:

```ts
function handleMessage(message: any, sender: browser.runtime.Sender) {
Expand All @@ -59,7 +36,7 @@ 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`.
Depending on the manifest version, browser, and permissions, 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.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ describe('Background Entrypoint', () => {
fakeBrowser.reset();
});

it("should log the extenion's runtime ID", () => {
it("should log the extension's runtime ID", () => {
const id = 'some-id';
fakeBrowser.runtime.id = id;

Expand Down
1 change: 0 additions & 1 deletion packages/wxt-demo/wxt.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { defineConfig } from 'wxt';

export default defineConfig({
srcDir: 'src',
extensionApi: 'chrome',
manifest: {
permissions: ['storage'],
default_locale: 'en',
Expand Down
2 changes: 2 additions & 0 deletions packages/wxt/e2e/tests/auto-imports.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ describe('Auto Imports', () => {
/// <reference types="./types/paths.d.ts" />
/// <reference types="./types/i18n.d.ts" />
/// <reference types="./types/globals.d.ts" />
/// <reference types="@types/chrome" />
/// <reference types="./types/imports.d.ts" />
"
`);
Expand Down Expand Up @@ -93,6 +94,7 @@ describe('Auto Imports', () => {
/// <reference types="./types/paths.d.ts" />
/// <reference types="./types/i18n.d.ts" />
/// <reference types="./types/globals.d.ts" />
/// <reference types="@types/chrome" />
"
`,
);
Expand Down
20 changes: 4 additions & 16 deletions packages/wxt/e2e/tests/modules.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -191,10 +191,7 @@ describe('Module Helpers', () => {
);
const expectedText = addPluginModule(project);

await project.build({
// reduce build output when comparing test failures
extensionApi: 'chrome',
});
await project.build();

await expect(project.serializeOutput()).resolves.toContain(expectedText);
});
Expand All @@ -211,10 +208,7 @@ describe('Module Helpers', () => {
);
const expectedText = addPluginModule(project);

await project.build({
// reduce build output when comparing test failures
extensionApi: 'chrome',
});
await project.build();

await expect(project.serializeOutput()).resolves.toContain(expectedText);
});
Expand All @@ -232,10 +226,7 @@ describe('Module Helpers', () => {
);
const expectedText = addPluginModule(project);

await project.build({
// reduce build output when comparing test failures
extensionApi: 'chrome',
});
await project.build();

await expect(project.serializeOutput()).resolves.toContain(expectedText);
});
Expand All @@ -248,10 +239,7 @@ describe('Module Helpers', () => {
);
const expectedText = addPluginModule(project);

await project.build({
// reduce build output when comparing test failures
extensionApi: 'chrome',
});
await project.build();

await expect(project.serializeOutput()).resolves.toContain(expectedText);
});
Expand Down
6 changes: 0 additions & 6 deletions packages/wxt/e2e/tests/output-structure.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -262,9 +262,6 @@ describe('Output Directory Structure', () => {
project.addFile('entrypoints/popup/main.ts', `logHello('popup')`);

await project.build({
// Simplify the build output for comparison
extensionApi: 'chrome',

vite: () => ({
build: {
// Make output for snapshot readible
Expand Down Expand Up @@ -347,9 +344,6 @@ describe('Output Directory Structure', () => {
project.addFile('entrypoints/popup/main.ts', `logHello('popup')`);

await project.build({
// Simplify the build output for comparison
extensionApi: 'chrome',

vite: () => ({
build: {
// Make output for snapshot readible
Expand Down
1 change: 1 addition & 0 deletions packages/wxt/e2e/tests/typescript-project.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,7 @@ describe('TypeScript Project', () => {
/// <reference types="./types/paths.d.ts" />
/// <reference types="./types/i18n.d.ts" />
/// <reference types="./types/globals.d.ts" />
/// <reference types="@types/chrome" />
/// <reference types="./types/imports.d.ts" />
"
`);
Expand Down
19 changes: 0 additions & 19 deletions packages/wxt/e2e/tests/user-config.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { describe, it, expect } from 'vitest';
import { TestProject } from '../utils';
import { InlineConfig } from '../../src/types';

describe('User Config', () => {
// Root directory is tested with all tests.
Expand Down Expand Up @@ -88,24 +87,6 @@ describe('User Config', () => {
`);
});

it('should exclude the polyfill when extensionApi="chrome"', async () => {
const buildBackground = async (config?: InlineConfig) => {
const background = `export default defineBackground(() => console.log(browser.runtime.id));`;
const projectWithPolyfill = new TestProject();
projectWithPolyfill.addFile('entrypoints/background.ts', background);
await projectWithPolyfill.build(config);
return await projectWithPolyfill.serializeFile(
'.output/chrome-mv3/background.js',
);
};

const withPolyfill = await buildBackground();
const withoutPolyfill = await buildBackground({
extensionApi: 'chrome',
});
expect(withoutPolyfill).not.toBe(withPolyfill);
});

it('should respect changing config files', async () => {
const project = new TestProject();
project.addFile(
Expand Down
12 changes: 3 additions & 9 deletions packages/wxt/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,8 @@
"default": "./dist/sandbox/index.mjs"
},
"./browser": {
"types": "./dist/browser/index.d.ts",
"default": "./dist/browser/index.mjs"
},
"./browser/chrome": {
"types": "./dist/browser/chrome.d.ts",
"import": "./dist/browser/chrome.mjs"
"types": "./dist/browser.d.ts",
"default": "./dist/browser.mjs"
},
"./testing": {
"types": "./dist/testing/index.d.ts",
Expand Down Expand Up @@ -83,7 +79,6 @@
"dependencies": {
"@aklinker1/rollup-plugin-visualizer": "5.12.0",
"@types/chrome": "^0.0.269",
"@types/webextension-polyfill": "^0.10.7",
"@webext-core/fake-browser": "^1.3.1",
"@webext-core/isolated-element": "^1.1.2",
"@webext-core/match-patterns": "^1.0.3",
Expand Down Expand Up @@ -124,8 +119,7 @@
"unimport": "^3.13.1",
"vite": "^5.4.8",
"vite-node": "^2.1.2",
"web-ext-run": "^0.2.1",
"webextension-polyfill": "^0.12.0"
"web-ext-run": "^0.2.1"
},
"devDependencies": {
"@aklinker1/check": "^1.4.5",
Expand Down
19 changes: 13 additions & 6 deletions packages/wxt/src/browser/chrome.ts → packages/wxt/src/browser.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
/// <reference types="chrome" />
/**
* EXPERIMENTAL
*
* Includes the `chrome` API and types when using `extensionApi: 'chrome'`.
*
* @module wxt/browser/chrome
* @module wxt/browser
*/
import type { WxtRuntime, WxtI18n } from './index';

/**
* This interface is empty because it is generated per-project when running `wxt prepare`. See:
* - `.wxt/types/paths.d.ts`
*/
export interface WxtRuntime {}

/**
* This interface is empty because it is generated per-project when running `wxt prepare`. See:
* - `.wxt/types/i18n.d.ts`
*/
export interface WxtI18n {}

export type WxtBrowser = Omit<typeof chrome, 'runtime' | 'i18n'> & {
runtime: WxtRuntime & Omit<(typeof chrome)['runtime'], 'getURL'>;
Expand Down
88 changes: 0 additions & 88 deletions packages/wxt/src/browser/index.ts

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ describe('Content Script Context', () => {
const onInvalidated = vi.fn();

ctx.onInvalidated(onInvalidated);
// @ts-expect-error
// @ts-ignore
delete fakeBrowser.runtime.id;
const isValid = ctx.isValid;

Expand Down
1 change: 0 additions & 1 deletion packages/wxt/src/core/builders/vite/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,6 @@ export async function createViteBuilder(
wxtPlugins.tsconfigPaths(wxtConfig),
wxtPlugins.noopBackground(),
wxtPlugins.globals(wxtConfig),
wxtPlugins.resolveExtensionApi(wxtConfig),
wxtPlugins.defineImportMeta(),
wxtPlugins.wxtPluginLoader(wxtConfig),
wxtPlugins.resolveAppConfig(wxtConfig),
Expand Down
Loading

0 comments on commit 70d842f

Please sign in to comment.