Compare commits

...

15 Commits

Author SHA1 Message Date
Aaron 229dfc822d 0.19.0-alpha1 2024-07-24 15:47:44 -05:00
Aaron 7177405c11 Fix dead links 2024-07-24 15:36:40 -05:00
Aaron 24e4abc087 Fix docs 2024-07-24 15:27:04 -05:00
Aaron ac9a4380b1 cleanup 2024-07-24 15:14:25 -05:00
Aaron 71620a02ab Fix tests 2024-07-24 15:13:38 -05:00
Aaron 0aca961629 Fix browser types 2024-07-24 14:59:36 -05:00
Aaron d64af5d4f0 Move option out of experimental 2024-07-24 13:39:30 -05:00
Aaron 7eb0a36245 WIP 2024-07-24 13:31:09 -05:00
Aaron 14bae66bba Update testing setup 2024-07-24 12:10:59 -05:00
Aaron e4ec4a28f9 Exclude dev-only declaration files from build 2024-07-24 11:30:44 -05:00
Aaron 7b32dd7062 Restructure types 2024-07-24 11:28:35 -05:00
Aaron b1ef71a77b Cleanup 2024-07-24 11:23:44 -05:00
Aaron 2f7fb30467 Fix everything 2024-07-24 11:06:43 -05:00
Aaron 4c684e7966 WIP 2024-07-24 08:54:16 -05:00
Aaron 8d5fbb2a32 feat(experimental): Replace disableWebextensionPolyfill with extensionApi 2024-07-24 08:51:34 -05:00
40 changed files with 276 additions and 207 deletions
+1 -1
View File
@@ -6,7 +6,7 @@ WXT uses the same tool as Nuxt for auto-imports, [`unimport`](https://github.com
Some WXT APIs can be used without importing them:
- [`browser`](/api/reference/wxt/browser/variables/browser) from `wxt/browser`, a small wrapper around `webextension-polyfill`
- [`browser`](/api/reference/wxt/browser/#browser) from `wxt/browser`, a small wrapper around `webextension-polyfill`
- [`defineContentScript`](/api/reference/wxt/sandbox/functions/defineContentScript) from `wxt/sandbox`
- [`defineBackground`](/api/reference/wxt/sandbox/functions/defineBackground) from `wxt/sandbox`
- [`defineUnlistedScript`](/api/reference/wxt/sandbox/functions/defineUnlistedScript) from `wxt/sandbox`
+1
View File
@@ -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",
+1
View File
@@ -2,6 +2,7 @@ import { defineConfig } from 'wxt';
export default defineConfig({
srcDir: 'src',
extensionApi: 'chrome',
manifest: {
permissions: ['storage'],
default_locale: 'en',
+1 -1
View File
@@ -13,7 +13,7 @@ export default defineBuildConfig([
{
builder: 'mkdist',
input: 'src',
pattern: ['**/*', '!**/__tests__', '!**/*.md', '!virtual'],
pattern: ['**/*', '!**/__tests__', '!**/*.md', '!virtual', '!@types'],
declaration: true,
},
],
+8 -16
View File
@@ -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);
@@ -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);
@@ -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);
@@ -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);
+18 -10
View File
@@ -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
@@ -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 };
@@ -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;
}
@@ -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
@@ -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;
@@ -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;
}
@@ -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;
}
+2 -4
View File
@@ -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();
@@ -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);
});
+20 -3
View File
@@ -1,7 +1,7 @@
{
"name": "wxt",
"type": "module",
"version": "0.18.15",
"version": "0.19.0-alpha1",
"description": "Next gen framework for developing web extensions",
"repository": {
"type": "git",
@@ -46,8 +46,16 @@
"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"
},
"./browser/webextension-polyfill": {
"types": "./dist/browser/webextension-polyfill.d.ts",
"import": "./dist/browser/webextension-polyfill.mjs"
},
"./testing": {
"types": "./dist/testing/index.d.ts",
@@ -121,6 +129,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",
@@ -138,5 +147,13 @@
"unbuild": "^2.0.0",
"vitest": "^2.0.3",
"vitest-plugin-random-seed": "^1.1.0"
},
"peerDependencies": {
"@types/chrome": "*"
},
"peerDependenciesMeta": {
"@types/chrome": {
"optional": true
}
}
}
@@ -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;
}
+1 -1
View File
@@ -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';
/**
+28
View File
@@ -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;
+4
View File
@@ -0,0 +1,4 @@
/**
* @module wxt/browser
*/
export * from './webextension-polyfill';
@@ -1,6 +1,9 @@
/**
* @module wxt/browser
* Includes the `browser` API and types when using `extensionApi: 'webextension-polyfill'` (the default).
*
* @module wxt/browser/webextension-polyfill
*/
import originalBrowser, { Browser, Runtime, I18n } from 'webextension-polyfill';
export interface AugmentedBrowser extends Browser {
@@ -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';
@@ -1,4 +1,4 @@
import { browser } from '../../browser';
import { browser } from 'wxt/browser';
export class WxtLocationChangeEvent extends Event {
static EVENT_NAME = getUniqueEventName('wxt:locationchange');
@@ -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}`;
}
@@ -1,4 +1,4 @@
import { browser } from '../../../browser';
import { browser } from 'wxt/browser';
import { ContentScriptContext } from '..';
import {
ContentScriptAnchoredOptions,
+3 -3
View File
@@ -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),
@@ -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),
],
};
@@ -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),
],
};
@@ -1,33 +0,0 @@
import { ResolvedConfig } from '../../../../types';
import type * as vite from 'vite';
/**
* Apply the experimental config for disabling the polyfill. It works by aliasing the
* `webextension-polyfill` module to a virtual module and exporting the `chrome` global from the
* virtual module.
*/
export function excludeBrowserPolyfill(config: ResolvedConfig): vite.Plugin {
const virtualId = 'virtual:wxt-webextension-polyfill-disabled';
return {
name: 'wxt:exclude-browser-polyfill',
config() {
// Only apply the config if we're disabling the polyfill
if (config.experimental.includeBrowserPolyfill) return;
return {
resolve: {
alias: {
'webextension-polyfill': virtualId,
},
},
};
},
load(id) {
if (id === virtualId) {
// Use chrome instead of the polyfill when disabled.
return 'export default chrome';
}
},
};
}
@@ -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'],
},
};
},
};
}
@@ -8,8 +8,8 @@ export * from './noopBackground';
export * from './cssEntrypoints';
export * from './bundleAnalysis';
export * from './globals';
export * from './webextensionPolyfillMock';
export * from './excludeBrowserPolyfill';
export * from './extensionApiMock';
export * from './resolveExtensionApi';
export * from './entrypointGroupGlobals';
export * from './defineImportMeta';
export * from './removeEntrypointMainFunction';
@@ -0,0 +1,27 @@
import { ResolvedConfig } from '../../../../types';
import type * as vite from 'vite';
/**
* Apply the experimental config for which extension API is used. This only
* effects the extension API included at RUNTIME - during development, types
* depend on the import.
*
* NOTE: this only works if we import `wxt/browser` instead of using the relative path.
*/
export function resolveExtensionApi(config: ResolvedConfig): vite.Plugin {
return {
name: 'wxt:resolve-extension-api',
config() {
// Only apply the config if we're disabling the polyfill
if (config.extensionApi === 'webextension-polyfill') return;
return {
resolve: {
alias: [
{ find: /^wxt\/browser$/, replacement: 'wxt/browser/chrome' },
],
},
};
},
};
}
@@ -1,41 +0,0 @@
import path from 'node:path';
import type * as vite from 'vite';
import { ResolvedConfig } from '../../../../types';
/**
* Mock `webextension-polyfill` by inlining all dependencies that import it and adding a custom
* alias so that Vite resolves to a mocked version of the module.
*
* There are two ways to mark a module as inline:
* 1. Use partial file paths ("wxt/dist/browser.js") in the `test.server.deps.inline` option.
* 2. Use module names ("wxt" or "@webext-core/messaging") in the `ssr.noExternalize` option.
*
* This plugin uses the second approach since it's a little more intuative to understand.
*
* TODO: Detect non-wxt dependencies (like `@webext-core/*`) that import `webextension-polyfill` via
* `npm list` and inline them automatically.
*/
export function webextensionPolyfillMock(
config: ResolvedConfig,
): vite.PluginOption {
return {
name: 'wxt:testing-inline-deps',
config() {
return {
resolve: {
alias: {
// Alias to use a mocked version of the polyfill
'webextension-polyfill': path.resolve(
config.wxtModuleDir,
'dist/virtual/mock-browser',
),
},
},
ssr: {
// Inline all WXT modules
noExternal: ['wxt'],
},
};
},
};
}
@@ -42,6 +42,11 @@ export async function generateTypesDir(
// import.meta.env.*
entries.push(await getGlobalsDeclarationEntry());
// @types/chrome
if (wxt.config.extensionApi === 'chrome') {
entries.push({ module: '@types/chrome' });
}
// tsconfig.json
entries.push(await getTsConfigEntry());
@@ -85,13 +90,13 @@ async function getPathsDeclarationEntry(
.join('\n');
const template = `// Generated by wxt
import "wxt/browser";
import "${wxt.config.browserModule}";
declare module "wxt/browser" {
declare module "${wxt.config.browserModule}" {
export type PublicPath =
{{ union }}
type HtmlPublicPath = Extract<PublicPath, \`\${string}.html\`>
export interface WxtRuntime extends Runtime.Static {
export interface WxtRuntime {
getURL(path: PublicPath): string;
getURL(path: \`\${HtmlPublicPath}\${string}\`): string;
}
@@ -108,9 +113,9 @@ declare module "wxt/browser" {
async function getI18nDeclarationEntry(): Promise<WxtDirFileEntry> {
const defaultLocale = wxt.config.manifest.default_locale;
const template = `// Generated by wxt
import "wxt/browser";
import "${wxt.config.browserModule}";
declare module "wxt/browser" {
declare module "${wxt.config.browserModule}" {
/**
* See https://developer.chrome.com/docs/extensions/reference/i18n/#method-getMessage
*/
@@ -1,4 +1,4 @@
import type { Manifest } from '../../../browser';
import type { Manifest } from 'wxt/browser';
import { BuildOutput, Entrypoint, EntrypointGroup } from '../../../types';
import { generateTypesDir } from './generate-wxt-dir';
import { buildEntrypoints } from './build-entrypoints';
@@ -146,6 +146,8 @@ export async function resolveConfig(
{},
);
const extensionApi = mergedConfig.extensionApi ?? 'webextension-polyfill';
return {
browser,
command,
@@ -155,7 +157,13 @@ export async function resolveConfig(
filterEntrypoints,
env,
fsCache: createFsCache(wxtDir),
imports: await getUnimportOptions(wxtDir, srcDir, logger, mergedConfig),
imports: await getUnimportOptions(
wxtDir,
srcDir,
logger,
extensionApi,
mergedConfig,
),
logger,
manifest: await resolveManifestConfig(env, mergedConfig.manifest),
manifestVersion,
@@ -174,8 +182,10 @@ export async function resolveConfig(
analysis: resolveAnalysisConfig(root, mergedConfig),
userConfigMetadata: userConfigMetadata ?? {},
alias,
extensionApi,
browserModule:
extensionApi === 'chrome' ? 'wxt/browser/chrome' : 'wxt/browser',
experimental: defu(mergedConfig.experimental, {
includeBrowserPolyfill: true,
entrypointImporter: 'jiti' as const,
}),
dev: {
@@ -306,6 +316,7 @@ async function getUnimportOptions(
wxtDir: string,
srcDir: string,
logger: Logger,
extensionApi: ResolvedConfig['extensionApi'],
config: InlineConfig,
): Promise<WxtResolvedUnimportOptions | false> {
if (config.imports === false) return false;
@@ -324,7 +335,10 @@ async function getUnimportOptions(
// ignored.
ignore: ['options'],
},
{ package: 'wxt/browser' },
{
package:
extensionApi === 'chrome' ? 'wxt/browser/chrome' : 'wxt/browser',
},
{ package: 'wxt/sandbox' },
{ package: 'wxt/storage' },
],
@@ -1,4 +1,4 @@
import type { Manifest, Scripting } from '../../browser';
import type { Manifest, Scripting } from 'wxt/browser';
import { ContentScriptEntrypoint, ResolvedConfig } from '../../types';
import { getEntrypointBundlePath } from './entrypoints';
+1 -1
View File
@@ -1,4 +1,4 @@
import type { Manifest } from '../../browser';
import type { Manifest } from 'wxt/browser';
import {
Entrypoint,
BackgroundEntrypoint,
@@ -4,7 +4,7 @@
import { resolve } from 'path';
import { faker } from '@faker-js/faker';
import merge from 'lodash.merge';
import { Commands, type Manifest } from '../../../browser';
import { Commands, type Manifest } from 'wxt/browser';
import {
FsCache,
ResolvedConfig,
@@ -296,8 +296,9 @@ export const fakeResolvedConfig = fakeObjectCreator<ResolvedConfig>(() => {
transformManifest: () => {},
userConfigMetadata: {},
alias: {},
extensionApi: 'webextension-polyfill',
browserModule: 'wxt/browser',
experimental: {
includeBrowserPolyfill: true,
entrypointImporter: 'jiti',
},
dev: {
+1 -1
View File
@@ -5,7 +5,7 @@
*
* @module wxt/storage
*/
import { Storage, browser } from './browser';
import { Storage, browser } from 'wxt/browser';
import { dequal } from 'dequal/lite';
import { logger } from './sandbox/utils/logger';
import { toArray } from './core/utils/arrays';
+20 -17
View File
@@ -3,7 +3,7 @@ import {
download,
tsconfigPaths,
globals,
webextensionPolyfillMock,
extensionApiMock,
resolveAppConfig,
} from '../core/builders/vite/plugins';
import { resolveConfig } from '../core/utils/building';
@@ -26,20 +26,23 @@ import { createUnimport } from 'unimport';
*
* @param inlineConfig Customize WXT's config for testing. Any config specified here overrides the config from your `wxt.config.ts` file.
*/
export function WxtVitest(inlineConfig?: InlineConfig): vite.PluginOption {
return resolveConfig(inlineConfig ?? {}, 'serve').then(async (config) => {
const plugins = [
webextensionPolyfillMock(config),
globals(config),
download(config),
tsconfigPaths(config),
resolveAppConfig(config),
];
if (config.imports !== false) {
const unimport = createUnimport(config.imports);
await unimport.init();
plugins.push(unimportPlugin(unimport));
}
return plugins;
});
export async function WxtVitest(
inlineConfig?: InlineConfig,
): Promise<vite.PluginOption[]> {
const config = await resolveConfig(inlineConfig ?? {}, 'serve');
const plugins: vite.PluginOption[] = [
globals(config),
download(config),
tsconfigPaths(config),
resolveAppConfig(config),
extensionApiMock(config),
];
if (config.imports !== false) {
const unimport = createUnimport(config.imports);
await unimport.init();
plugins.push(unimportPlugin(unimport));
}
return plugins;
}
@@ -1,8 +1,8 @@
import type * as vite from 'vite';
import type { Manifest, Scripting } from '../browser';
import type { Manifest, Scripting } from 'wxt/browser';
import { UnimportOptions, Import } from 'unimport';
import { LogLevel } from 'consola';
import { ContentScriptContext } from '../client/content-scripts/content-script-context';
import type { ContentScriptContext } from './client/content-scripts/content-script-context';
import type { PluginVisualizerOptions } from '@aklinker1/rollup-plugin-visualizer';
import type { FSWatcher } from 'chokidar';
import { ResolvedConfig as C12ResolvedConfig } from 'c12';
@@ -292,36 +292,25 @@ export interface InlineConfig {
* }
*/
alias?: Record<string, string>;
/**
* Which extension API to use.
*
* - `"webextension-polyfill"`: Use `browser` and types from [`webextension-polyfill`](https://www.npmjs.com/package/webextension-polyfill).
* - `"chrome"` (unstable): Use the regular `chrome` (or `browser` for Firefox/Safari) globals provided by the browser. Types provided by [`@types/chrome`](https://www.npmjs.com/package/@types/chrome), make sure to install the package or types won't work.
*
* @default "webextension-polyfill"
*/
extensionApi?: 'webextension-polyfill' | 'chrome';
/**
* Experimental settings - use with caution.
*/
experimental?: {
/**
* Whether to use [`webextension-polyfill`](https://www.npmjs.com/package/webextension-polyfill)
* when importing `browser` from `wxt/browser`.
*
* When set to `false`, WXT will export the chrome global instead of the polyfill from
* `wxt/browser`.
*
* You should use `browser` to access the web extension APIs.
*
* @experimental This option will remain experimental until Manifest V2 is dead.
*
* @default true
* @example
* export default defineConfig({
* experimental: {
* includeBrowserPolyfill: false
* }
* })
*/
includeBrowserPolyfill?: boolean;
/**
* Method used to import entrypoint files during the build process to extract their options.
*
* - "jiti": Simplest and fastest, but doesn't allow using any imported variables outside the entrypoint's main function
* - "vite-runtime" (unstable): Uses Vite 5.3's new runtime API to import the entrypoints. Automatically includes vite config based on your wxt.config.ts file
* - "vite-node" (unstable): Uses `vite-node` to import the entrypoints. Automatically includes vite config based on your wxt.config.ts file
* - `"jiti"`: Simplest and fastest, but doesn't allow using any imported variables outside the entrypoint's main function
* - `"vite-runtime"` (unstable): Uses Vite 5.3's new runtime API to import the entrypoints. Automatically includes vite config based on your wxt.config.ts file
* - `"vite-node"` (unstable): Uses `vite-node` to import the entrypoints. Automatically includes vite config based on your wxt.config.ts file
*
* @see {@link https://wxt.dev/guide/go-further/entrypoint-side-effects.html|Entrypoint Side-effect Docs}
*
@@ -1202,8 +1191,9 @@ export interface ResolvedConfig {
* Import aliases to absolute paths.
*/
alias: Record<string, string>;
extensionApi: 'webextension-polyfill' | 'chrome';
browserModule: 'wxt/browser' | 'wxt/browser/chrome';
experimental: {
includeBrowserPolyfill: boolean;
entrypointImporter: 'jiti' | 'vite-runtime' | 'vite-node';
};
dev: {
+3 -2
View File
@@ -1,3 +1,4 @@
import { fakeBrowser as mockBrowser } from 'wxt/testing';
import { fakeBrowser } from 'wxt/testing';
export default mockBrowser;
export const browser = fakeBrowser;
export default fakeBrowser;
+1 -1
View File
@@ -1,7 +1,7 @@
{
"extends": "../../../../tsconfig.base.json",
"compilerOptions": {
"types": ["vite/client", "../types/globals.d.ts"]
"types": ["vite/client", "../@types/globals.d.ts"]
},
"include": ["./*"]
}
+4 -18
View File
@@ -1,26 +1,22 @@
// Types required to make the virtual modules happy.
declare module 'virtual:user-background-entrypoint' {
const definition: { main: () => void };
const definition: import('wxt').BackgroundDefinition;
export default definition;
}
declare module 'virtual:user-content-script-isolated-world-entrypoint' {
const definition: {
main: (
ctx: import('wxt/client').ContentScriptContext,
) => void | Promise<void>;
};
const definition: import('wxt').IsolatedWorldContentScriptDefinition;
export default definition;
}
declare module 'virtual:user-content-script-main-world-entrypoint' {
const definition: { main: () => void | Promise<void> };
const definition: import('wxt').MainWorldContentScriptDefinition;
export default definition;
}
declare module 'virtual:user-unlisted-script-entrypoint' {
const definition: { main: () => void | Promise<void> };
const definition: import('wxt').UnlistedScriptDefinition;
export default definition;
}
@@ -28,16 +24,6 @@ declare module 'wxt/browser' {
export const browser: import('webextension-polyfill').Browser;
}
declare module 'wxt/client' {
export class ContentScriptContext {
constructor(name: string, options: any);
}
}
declare module 'wxt/testing' {
export const fakeBrowser: import('webextension-polyfill').Browser;
}
declare module 'virtual:wxt-plugins' {
export function initPlugins(): void;
}
+3 -1
View File
@@ -3,7 +3,9 @@
"src/client/index.ts",
"src/testing/index.ts",
"src/sandbox/index.ts",
"src/browser.ts",
"src/browser/index.ts",
"src/browser/chrome.ts",
"src/browser/webextension-polyfill.ts",
"src/index.ts",
"src/storage.ts",
"src/modules.ts"
+4 -1
View File
@@ -18,7 +18,10 @@ export default defineConfig({
ignored: '**/dist/**',
},
},
plugins: [RandomSeed()],
plugins: [
// @ts-expect-error: Vite version mismatch
RandomSeed(),
],
resolve: {
alias: {
'wxt/testing': path.resolve('src/testing'),
+28 -1
View File
@@ -316,6 +316,9 @@ importers:
'@faker-js/faker':
specifier: ^8.4.1
version: 8.4.1
'@types/chrome':
specifier: ^0.0.268
version: 0.0.268
'@types/fs-extra':
specifier: ^11.0.4
version: 11.0.4
@@ -377,6 +380,9 @@ importers:
specifier: ^18.3.1
version: 18.3.1(react@18.3.1)
devDependencies:
'@types/chrome':
specifier: ^0.0.268
version: 0.0.268
'@types/react':
specifier: ^18.3.3
version: 18.3.3
@@ -1915,9 +1921,26 @@ packages:
'@babel/types': 7.24.7
dev: false
/@types/chrome@0.0.268:
resolution: {integrity: sha512-7N1QH9buudSJ7sI8Pe4mBHJr5oZ48s0hcanI9w3wgijAlv1OZNUZve9JR4x42dn5lJ5Sm87V1JNfnoh10EnQlA==}
dependencies:
'@types/filesystem': 0.0.36
'@types/har-format': 1.2.15
dev: true
/@types/estree@1.0.5:
resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==}
/@types/filesystem@0.0.36:
resolution: {integrity: sha512-vPDXOZuannb9FZdxgHnqSwAG/jvdGM8Wq+6N4D/d80z+D4HWH+bItqsZaVRQykAn6WEVeEkLm2oQigyHtgb0RA==}
dependencies:
'@types/filewriter': 0.0.33
dev: true
/@types/filewriter@0.0.33:
resolution: {integrity: sha512-xFU8ZXTw4gd358lb2jw25nxY9QAgqn2+bKKjKOYfNCzN4DKCFetK7sPtrlpg66Ywe3vWY9FNxprZawAh9wfJ3g==}
dev: true
/@types/fs-extra@11.0.4:
resolution: {integrity: sha512-yTbItCNreRooED33qjunPthRcSjERP1r4MqCZc7wv0u2sUkzTFp45tgUfS5+r7FrZPdmCCNflLhVSP/o+SemsQ==}
dependencies:
@@ -1925,6 +1948,10 @@ packages:
'@types/node': 20.10.3
dev: true
/@types/har-format@1.2.15:
resolution: {integrity: sha512-RpQH4rXLuvTXKR0zqHq3go0RVXYv/YVqv4TnPH95VbwUxZdQlK1EtcMvQvMpDngHbt13Csh9Z4qT9AbkiQH5BA==}
dev: true
/@types/hast@3.0.4:
resolution: {integrity: sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==}
dependencies:
@@ -7239,7 +7266,7 @@ packages:
peerDependencies:
vite: ^4.0.0 || ^5.0.0
dependencies:
vite: 5.3.4(@types/node@20.14.11)
vite: 5.3.4(sass@1.77.8)
dev: true
/vitest@2.0.3: