Skip to content

Feature: Support loading additional extensions alongside main extension #1997

@0xBigBoss

Description

@0xBigBoss

Feature Request: Support loading additional extensions via additionalExtensions config

Repository: https://github.com/wxt-dev/wxt

Summary

Add support for loading additional extensions alongside the WXT extension during development via a new additionalExtensions config option in webExt.

Use Case

When developing browser extensions with WXT, developers often need to load multiple extensions simultaneously:

  1. WebAuthn Testing: Extensions using WebAuthn require a virtual authenticator extension for automated testing
  2. Debugging Tools: Loading React DevTools or Redux DevTools alongside the main extension
  3. Integration Testing: Testing interactions between multiple extensions
  4. Development Helpers: Loading helper extensions that provide test fixtures or mock APIs

Currently, developers must manually load additional extensions through chrome://extensions after WXT opens the browser, which:

  • Breaks the development workflow
  • Doesn't persist across browser restarts in dev mode
  • Can't be automated in CI/Tilt environments

Proposed API

Add an additionalExtensions config option to the webExt configuration:

// wxt.config.ts
export default defineConfig({
  webExt: {
    startUrls: ['http://localhost:3000'],
    // New option: array of paths to additional extension directories
    additionalExtensions: [
      '/path/to/webauthn-extension',
      '/path/to/devtools-extension',
    ],
  },
})

TypeScript Types

interface WebExtConfig {
  // ... existing options

  /**
   * Additional extension directories to load alongside the main extension.
   * Useful for loading helper extensions like WebAuthn authenticators or debugging tools.
   * Only supported for Chromium browsers.
   */
  additionalExtensions?: string[];
}

Proposed Implementation

Pass the additionalExtensions array to web-ext-run as additionalSourceDirs:

// dist/core/runners/web-ext.mjs
const finalConfig = {
  ...userConfig,
  target: wxt.config.browser === "firefox" ? "firefox-desktop" : "chromium",
  sourceDir: wxt.config.outDir,
  // Pass additional extensions to web-ext-run
  additionalSourceDirs: wxtUserConfig?.additionalExtensions ?? [],
  noReloadManagerExtension: true,
  noReload: true,
  noInput: true,
};

Diff

--- a/dist/core/runners/web-ext.mjs
+++ b/dist/core/runners/web-ext.mjs
@@ -50,6 +50,8 @@ export function createWebExtRunner() {
         target: wxt.config.browser === "firefox" ? "firefox-desktop" : "chromium",
         sourceDir: wxt.config.outDir,
         // Don't add a "Reload Manager" extension alongside dev extension, WXT
+        // Support loading additional extensions (requires web-ext-run support)
+        additionalSourceDirs: wxtUserConfig?.additionalExtensions ?? [],
         // already handles reloads intenrally.
         noReloadManagerExtension: true,
         // WXT handles reloads, so disable auto-reload behaviors in web-ext

Example Usage

// wxt.config.ts
const webAuthnExtensionPath = process.env.WEBAUTHN_EXTENSION_PATH;

export default defineConfig({
  modules: ['@wxt-dev/module-react'],

  webExt: {
    startUrls: ['http://localhost:5174'],
    ...(webAuthnExtensionPath ? {
      additionalExtensions: [webAuthnExtensionPath],
      // Optionally use persistent profile for auth state
      chromiumProfile: process.env.CHROME_PROFILE_DIR,
      keepProfileChanges: !!process.env.CHROME_PROFILE_DIR,
    } : {}),
  },
})

Dependencies

This feature requires web-ext-run to support loading multiple extensions. A corresponding feature request should be filed there for additionalSourceDirs support.

Upstream issue: (link to web-ext-run issue when created)

Notes

  • Additional extensions are loaded via CDP Extensions.loadUnpacked (Chrome 126+) or --load-extension flag (older versions)
  • Only the main WXT extension receives HMR/reload capabilities
  • Additional extensions are loaded once at browser startup
  • Only supported for Chromium browsers (Chrome, Edge, etc.)

Alternatives Considered

  1. Using chromiumArgs with --load-extension: Doesn't work with Chrome 126+ which uses CDP instead of the flag
  2. Post-launch CDP injection: Would require connecting to Chrome's debugging port separately, adding complexity

Real-World Use Case

We're building a Canton Network wallet extension that uses WebAuthn for authentication. During development and E2E testing with Playwright, we need to load a virtual WebAuthn authenticator extension alongside our main extension. This feature would enable:

# Tiltfile
if enable_webauthn:
    extension_env["WEBAUTHN_EXTENSION_PATH"] = webauthn_extension_path

Without this feature, we have to use complex workarounds involving CDP injection scripts that are fragile and don't integrate well with WXT's development workflow.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions