Skip to content

Commit

Permalink
feat(experimental): First-class support for excluding `webextension-p…
Browse files Browse the repository at this point in the history
…olyfill` (#847)
  • Loading branch information
aklinker1 authored Jul 24, 2024
1 parent 5eb5be7 commit f1bb7cb
Show file tree
Hide file tree
Showing 38 changed files with 264 additions and 204 deletions.
1 change: 1 addition & 0 deletions packages/wxt-demo/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
"react-dom": "^18.3.1"
},
"devDependencies": {
"@types/chrome": "^0.0.268",
"@types/react": "^18.3.3",
"@types/react-dom": "^18.3.0",
"sass": "^1.77.8",
Expand Down
1 change: 1 addition & 0 deletions packages/wxt-demo/wxt.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { defineConfig } from 'wxt';

export default defineConfig({
srcDir: 'src',
extensionApi: 'chrome',
manifest: {
permissions: ['storage'],
default_locale: 'en',
Expand Down
2 changes: 1 addition & 1 deletion packages/wxt/build.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export default defineBuildConfig([
{
builder: 'mkdist',
input: 'src',
pattern: ['**/*', '!**/__tests__', '!**/*.md', '!virtual'],
pattern: ['**/*', '!**/__tests__', '!**/*.md', '!virtual', '!@types'],
declaration: true,
},
],
Expand Down
24 changes: 8 additions & 16 deletions packages/wxt/e2e/tests/modules.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -192,10 +192,8 @@ describe('Module Helpers', () => {
const expectedText = addPluginModule(project);

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

await expect(project.serializeOutput()).resolves.toContain(expectedText);
Expand All @@ -214,10 +212,8 @@ describe('Module Helpers', () => {
const expectedText = addPluginModule(project);

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

await expect(project.serializeOutput()).resolves.toContain(expectedText);
Expand All @@ -237,10 +233,8 @@ describe('Module Helpers', () => {
const expectedText = addPluginModule(project);

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

await expect(project.serializeOutput()).resolves.toContain(expectedText);
Expand All @@ -255,10 +249,8 @@ describe('Module Helpers', () => {
const expectedText = addPluginModule(project);

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

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

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

vite: () => ({
build: {
// Make output for snapshot readible
Expand All @@ -278,6 +277,7 @@ describe('Output Directory Structure', () => {
.toMatchInlineSnapshot(`
".output/chrome-mv3/background.js
----------------------------------------
var _a, _b;
import { l as logHello, i as initPlugins } from "./chunks/_virtual_wxt-plugins-OjKtWpmY.js";
function defineBackground(arg) {
if (typeof arg === "function") return { main: arg };
Expand All @@ -289,7 +289,11 @@ describe('Output Directory Structure', () => {
logHello("background");
}
});
chrome;
// @ts-expect-error
((_b = (_a = globalThis.browser) == null ? void 0 : _a.runtime) == null ? void 0 : _b.id) == null ? globalThis.chrome : (
// @ts-expect-error
globalThis.browser
);
function print(method, ...args) {
return;
}
Expand Down Expand Up @@ -343,10 +347,9 @@ describe('Output Directory Structure', () => {
project.addFile('entrypoints/popup/main.ts', `logHello('popup')`);

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

vite: () => ({
build: {
// Make output for snapshot readible
Expand All @@ -361,6 +364,7 @@ describe('Output Directory Structure', () => {
----------------------------------------
var _background = function() {
"use strict";
var _a, _b;
function defineBackground(arg) {
if (typeof arg === "function") return { main: arg };
return arg;
Expand All @@ -377,7 +381,11 @@ describe('Output Directory Structure', () => {
_background;
function initPlugins() {
}
chrome;
// @ts-expect-error
((_b = (_a = globalThis.browser) == null ? void 0 : _a.runtime) == null ? void 0 : _b.id) == null ? globalThis.chrome : (
// @ts-expect-error
globalThis.browser
);
function print(method, ...args) {
return;
}
Expand Down
2 changes: 1 addition & 1 deletion packages/wxt/e2e/tests/typescript-project.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ describe('TypeScript Project', () => {
| "/popup.html"
| "/sandbox.html"
type HtmlPublicPath = Extract<PublicPath, \`\${string}.html\`>
export interface WxtRuntime extends Runtime.Static {
export interface WxtRuntime {
getURL(path: PublicPath): string;
getURL(path: \`\${HtmlPublicPath}\${string}\`): string;
}
Expand Down
6 changes: 2 additions & 4 deletions packages/wxt/e2e/tests/user-config.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ describe('User Config', () => {
`);
});

it('should exclude the polyfill when the experimental setting is set to false', async () => {
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();
Expand All @@ -101,9 +101,7 @@ describe('User Config', () => {

const withPolyfill = await buildBackground();
const withoutPolyfill = await buildBackground({
experimental: {
includeBrowserPolyfill: false,
},
extensionApi: 'chrome',
});
expect(withoutPolyfill).not.toBe(withPolyfill);
});
Expand Down
17 changes: 15 additions & 2 deletions packages/wxt/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,12 @@
"default": "./dist/sandbox/index.mjs"
},
"./browser": {
"types": "./dist/browser.d.ts",
"default": "./dist/browser.mjs"
"types": "./dist/browser/index.d.ts",
"default": "./dist/browser/index.mjs"
},
"./browser/chrome": {
"types": "./dist/browser/chrome.d.ts",
"import": "./dist/browser/chrome.mjs"
},
"./testing": {
"types": "./dist/testing/index.d.ts",
Expand Down Expand Up @@ -121,6 +125,7 @@
"devDependencies": {
"@aklinker1/check": "^1.3.1",
"@faker-js/faker": "^8.4.1",
"@types/chrome": "^0.0.268",
"@types/fs-extra": "^11.0.4",
"@types/lodash.merge": "^4.6.9",
"@types/natural-compare": "^1.4.3",
Expand All @@ -138,5 +143,13 @@
"unbuild": "^2.0.0",
"vitest": "^2.0.3",
"vitest-plugin-random-seed": "^1.1.0"
},
"peerDependencies": {
"@types/chrome": "*"
},
"peerDependenciesMeta": {
"@types/chrome": {
"optional": true
}
}
}
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,3 @@ declare module 'web-ext-run/util/logger' {
}
export const consoleStream: IConsoleStream;
}

declare module 'wxt/browser' {
// Overridden when types are generated per project
export type PublicPath = string;
}
File renamed without changes.
2 changes: 1 addition & 1 deletion packages/wxt/src/__tests__/storage.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { fakeBrowser } from '@webext-core/fake-browser';
import { describe, it, expect, beforeEach, vi, expectTypeOf } from 'vitest';
import { browser } from '../browser';
import { browser } from 'wxt/browser';
import { WxtStorageItem, storage } from '../storage';

/**
Expand Down
28 changes: 28 additions & 0 deletions packages/wxt/src/browser/chrome.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/// <reference types="chrome" />
/**
* EXPERIMENTAL
*
* Includes the `chrome` API and types when using `extensionApi: 'chrome'`.
*
* @module wxt/browser/chrome
*/

export interface WxtRuntime {
// Overriden per-project
}
export interface WxtI18n {
// Overriden per-project
}

export type Chrome = typeof chrome;
export type WxtBrowser = Omit<Chrome, 'runtime' | 'i18n'> & {
runtime: WxtRuntime & Omit<Chrome['runtime'], 'getURL'>;
i18n: WxtI18n & Omit<Chrome['i18n'], 'getMessage'>;
};

export const browser: WxtBrowser =
// @ts-expect-error
globalThis.browser?.runtime?.id == null
? globalThis.chrome
: // @ts-expect-error
globalThis.browser;
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
/**
* Includes the `browser` API and types when using `extensionApi: 'webextension-polyfill'` (the default).
*
* @module wxt/browser
*/

import originalBrowser, { Browser, Runtime, I18n } from 'webextension-polyfill';

export interface AugmentedBrowser extends Browser {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ContentScriptDefinition } from '../../types';
import { browser } from '../../browser';
import { browser } from 'wxt/browser';
import { logger } from '../../sandbox/utils/logger';
import { WxtLocationChangeEvent, getUniqueEventName } from './custom-events';
import { createLocationWatcher } from './location-watcher';
Expand Down
4 changes: 2 additions & 2 deletions packages/wxt/src/client/content-scripts/custom-events.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { browser } from '../../browser';
import { browser } from 'wxt/browser';

export class WxtLocationChangeEvent extends Event {
static EVENT_NAME = getUniqueEventName('wxt:locationchange');
Expand All @@ -22,5 +22,5 @@ export function getUniqueEventName(eventName: string): string {
? 'build'
: import.meta.env.ENTRYPOINT;

return `${browser.runtime.id}:${entrypointName}:${eventName}`;
return `${browser?.runtime?.id}:${entrypointName}:${eventName}`;
}
2 changes: 1 addition & 1 deletion packages/wxt/src/client/content-scripts/ui/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { browser } from '../../../browser';
import { browser } from 'wxt/browser';
import { ContentScriptContext } from '..';
import {
ContentScriptAnchoredOptions,
Expand Down
6 changes: 3 additions & 3 deletions packages/wxt/src/core/builders/vite/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ export async function createViteBuilder(
wxtPlugins.tsconfigPaths(wxtConfig),
wxtPlugins.noopBackground(),
wxtPlugins.globals(wxtConfig),
wxtPlugins.excludeBrowserPolyfill(wxtConfig),
wxtPlugins.resolveExtensionApi(wxtConfig),
wxtPlugins.defineImportMeta(),
wxtPlugins.wxtPluginLoader(wxtConfig),
wxtPlugins.resolveAppConfig(wxtConfig),
Expand Down Expand Up @@ -218,7 +218,7 @@ export async function createViteBuilder(
const baseConfig = await getBaseConfig();
const envConfig: vite.InlineConfig = {
plugins: [
wxtPlugins.webextensionPolyfillMock(wxtConfig),
wxtPlugins.extensionApiMock(wxtConfig),
wxtPlugins.removeEntrypointMainFunction(wxtConfig, path),
],
};
Expand All @@ -238,7 +238,7 @@ export async function createViteBuilder(
baseConfig.optimizeDeps.include = [];
const envConfig: vite.InlineConfig = {
plugins: [
wxtPlugins.webextensionPolyfillMock(wxtConfig),
wxtPlugins.extensionApiMock(wxtConfig),
wxtPlugins.removeEntrypointMainFunction(wxtConfig, path),
],
};
Expand Down

This file was deleted.

37 changes: 37 additions & 0 deletions packages/wxt/src/core/builders/vite/plugins/extensionApiMock.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import path from 'node:path';
import type * as vite from 'vite';
import { ResolvedConfig } from '../../../../types';

/**
* Mock `webextension-polyfill`, `wxt/browser`, and `wxt/browser/*` by inlining
* all dependencies that import them and adding a custom alias so that Vite
* resolves to a mocked version of the module.
*
* TODO: Detect non-wxt dependencies (like `@webext-core/*`) that import `webextension-polyfill` via
* `npm list` and inline them automatically.
*/
export function extensionApiMock(config: ResolvedConfig): vite.PluginOption {
return {
name: 'wxt:extension-api-mock',
config() {
const replacement = path.resolve(
config.wxtModuleDir,
'dist/virtual/mock-browser',
);
return {
resolve: {
alias: [
{ find: 'webextension-polyfill', replacement },
// wxt/browser, wxt/browser/...
{ find: /^wxt\/browser.*/, replacement },
],
},
ssr: {
// Inline all WXT modules so vite processes them so the aliases can
// be resolved
noExternal: ['wxt'],
},
};
},
};
}
Loading

0 comments on commit f1bb7cb

Please sign in to comment.