Registry / devops / web-ext

web-ext

JSON →
library10.1.0jsnpmunverified

web-ext is a command-line interface (CLI) tool developed by Mozilla to streamline the development, testing, and distribution of WebExtensions. It supports cross-browser compatibility, initially focusing on Firefox Extensions, but also providing features for Chromium-based browsers like Chrome and Opera. The current stable version is 10.1.0, with frequent updates, often on a monthly or bi-weekly basis, to support new browser versions, API schemas, and Node.js LTS releases. Key differentiators include its tight integration with Firefox's extension ecosystem, including signing and submission to addons.mozilla.org (AMO), and built-in linting for manifest and source file validation. While primarily a CLI, it offers limited programmatic API support for advanced use cases.

npm install web-ext
INSTALL
IMPORT
SIG · WEB-EXT
W
web-ext
devopsjavascriptv10.1.0
Install
Import
Disk
Pass rate
0/ 6
Env Coverage0 / 6
glibc
1822
musl
1822
Install & Compatibility
Where this runs
tested against v? · npm install
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
musl
node 18226 runs
build_error
glibc
node 18226 runs
build_error
Code
Verified usage

Verified import paths — ran on the pinned version, not inferred.

webExt.cmd.run
import webExt from 'web-ext'; webExt.cmd.run({ sourceDir: './path/to/your/extension/source', firefox: 'developer', }, { shouldExitProgram: false, });
const webExt = require('web-ext'); // CommonJS is not natively supported since v7.0.0; dynamic import or ESM required. // webExt.run(); // Incorrect API usage, functions are nested under .cmd
web-ext is primarily a CLI tool. Direct programmatic use is supported for ESM (Node.js native ES modules) since v7.0.0. CommonJS `require()` syntax requires dynamic imports. The API is considered internal and may have breaking changes in minor versions.
webExt.cmd.lint
import webExt from 'web-ext'; async function lintExtension() { try { const results = await webExt.cmd.lint({ sourceDir: './path/to/your/extension/source', // Optional: Set strict_min_version to '100' for stricter checks }, { shouldExitProgram: false, }); console.log('Linting complete:', results.summary); } catch (error) { console.error('Linting failed:', error); } } lintExtension();
import { lint } from 'web-ext'; // Incorrect named import for command functions. webExt.lint(); // Incorrect direct call, requires .cmd prefix and options object.
Like other commands, `lint` is accessible via `webExt.cmd`. It returns validation results and can be configured with options like `sourceDir` and `strict_min_version`.
Using via `npx` or `npm` scripts
npx web-ext run --source-dir ./extension-dist --firefox=nightly
node path/to/web-ext.js run --source-dir ./extension-dist // While technically possible, `npx` or global installation is the intended CLI usage.
The most common and recommended way to use web-ext for developers is via global installation (`npm install -g web-ext`), `npx`, or as an `npm script` in `package.json`. This abstracts away the Node.js API and leverages the CLI directly.

This quickstart demonstrates how to run a web extension in Firefox using `web-ext` via `child_process.spawn` from a Node.js script. It creates a minimal extension and launches Firefox with it, showing how to leverage `web-ext`'s CLI capabilities programmatically, which is the primary integration pattern.

import { spawn } from 'child_process'; import path from 'path'; import { fileURLToPath } from 'url'; const __dirname = path.dirname(fileURLToPath(import.meta.url)); const extensionSourceDir = path.join(__dirname, 'my-browser-extension'); console.log(`Starting web-ext to run extension from: ${extensionSourceDir}`); const webExtProcess = spawn('npx', [ 'web-ext', 'run', '--source-dir', extensionSourceDir, '--browser-console', '--firefox-profile', 'web-ext-dev-profile', '--keep-profile-changes', '--watch-file', path.join(extensionSourceDir, '**/*'), '--devtools' ], { stdio: 'inherit', shell: true }); webExtProcess.on('error', (err) => { console.error('Failed to start web-ext process:', err); }); webExtProcess.on('close', (code) => { console.log(`web-ext process exited with code ${code}`); }); // Example: Create a dummy extension directory for demonstration import { mkdirSync, writeFileSync, existsSync } from 'fs'; if (!existsSync(extensionSourceDir)) { mkdirSync(extensionSourceDir, { recursive: true }); mkdirSync(path.join(extensionSourceDir, 'icons'), { recursive: true }); writeFileSync(path.join(extensionSourceDir, 'manifest.json'), JSON.stringify({ "manifest_version": 2, "name": "My Basic Extension", "version": "1.0", "description": "A simple extension generated by web-ext quickstart.", "icons": { "48": "icons/icon-48.png" }, "browser_action": { "default_popup": "popup/popup.html" } }, null, 2)); mkdirSync(path.join(extensionSourceDir, 'popup'), { recursive: true }); writeFileSync(path.join(extensionSourceDir, 'popup/popup.html'), '<!DOCTYPE html><html><body><h1>Hello web-ext!</h1></body></html>'); writeFileSync(path.join(extensionSourceDir, 'icons/icon-48.png'), '<!-- Base64 encoded dummy image data for a 48x48 transparent PNG -->'); console.log('Dummy extension created in:', extensionSourceDir); } // To stop the process programmatically (optional, for longer-running tasks) // setTimeout(() => { // console.log('Attempting to kill web-ext process...'); // webExtProcess.kill(); // }, 60000); // Kills after 60 seconds
web-ext --version
Debug
Known issues
breakingSince web-ext v9.0.0, `.js` config files are no longer accepted due to Node.js module resolution changes. Configuration files must now use the `.cjs` or `.mjs` file extension.
fix
Rename your `web-ext-config.js` or similar configuration file to `web-ext-config.cjs` (for CommonJS) or `web-ext-config.mjs` (for ESM). Ensure the file exports the config object correctly (e.g., `module.exports = { ... }` for `.cjs` or `export default { ... }` for `.mjs`).
affects: >=9.0.0
breakingweb-ext now uses Node.js v22 by default since v10.0.0 and previously updated to Node.js v20 by default in v9.0.0. Older Node.js versions may not be officially supported or compatible.
fix
Ensure your development environment uses a current Node.js LTS version (>=20.0.0, ideally >=22.0.0 for v10+). Use a version manager like `nvm` to easily switch and manage Node.js versions (e.g., `nvm install lts/gallium` or `nvm install lts/iron`).
affects: >=9.0.0
gotchaDirect programmatic use of web-ext's internal API, while possible, has limited support and backward-incompatible changes may be introduced in minor or patch versions. It is primarily designed as a command-line tool.
fix
For scripting, prefer using `child_process.spawn` or `execa` to call the `web-ext` CLI directly. If using the programmatic API (available for ESM since v7.0.0), be aware that imports and API signatures might change between non-major releases. Always test thoroughly after updates.
affects: >=7.0.0
gotchaAs of web-ext v7.0.0, the `web-ext` npm package exports Node.js native ES modules only. Attempting to use `require()` directly in a CommonJS context for programmatic imports will fail.
fix
If you need to programmatically import `web-ext` in a CommonJS module, use dynamic `import()` (e.g., `const webExt = await import('web-ext');`). For new projects, consider using ESM by setting `"type": "module"` in your `package.json` or by using `.mjs` files.
affects: >=7.0.0
gotcha`web-ext lint` will emit a `MISSING_ADDON_ID` warning if your `manifest.json` does not include an `applications.gecko.id` (or `browser_specific_settings.gecko.id`) field, which is required for AMO submission.
fix
For extensions intended for distribution on AMO, ensure you add a unique `id` to the `applications.gecko` object in your `manifest.json` file. For example: `"applications": { "gecko": { "id": "your-addon-name@your-domain.com" } }`. This ID is crucial for updates and identifying your extension.
affects: >=9.1.0
Errors
Common errors & fixes
Error: Cannot find module 'web-ext' from '...' or 'require() of ES Module .../node_modules/web-ext/index.js from .../your-script.js not supported.'
Attempting to `require('web-ext')` in a CommonJS module, but `web-ext` >=7.0.0 is an ESM-only package.
fix
Use dynamic import: `const webExt = await import('web-ext');` or refactor your script to use ES modules (`.mjs` file or `"type": "module"` in `package.json`).
WARNING: config file <path>.js should be renamed to ".cjs" or ".mjs" file extension to ensure its format is not ambiguous. Config files with the ".js" file extension are deprecated and will not be loaded anymore in a future web-ext major version.
Using a `.js` file for web-ext configuration, which is deprecated and no longer supported since v9.0.0.
fix
Rename your configuration file from `.js` to `.cjs` (for CommonJS export) or `.mjs` (for ESM default export). Update the export syntax if necessary (e.g., `module.exports = { ... }` or `export default { ... }`).
Error: Missing required argument: --api-key and --api-secret (or environment variables WEB_EXT_API_KEY and WEB_EXT_API_SECRET)
Attempting to use `web-ext sign` without providing API credentials for addons.mozilla.org (AMO).
fix
When using `web-ext sign`, you must provide your AMO API key and secret either via command-line arguments (`--api-key <key> --api-secret <secret>`) or as environment variables (`WEB_EXT_API_KEY` and `WEB_EXT_API_SECRET`). Obtain these credentials from the AMO developer hub.
Upgrade
Version history
10.1.0latest on npm
Audit
Dependencies
addons-linterrequiredUsed for validating extension source code and manifest files against browser schemas.
pinorequiredUsed for logging within the web-ext tool.
openrequiredUsed to open URLs or files in the default browser, for example, opening documentation.
Agent activity
11 hits · last 30 days
node
8
Amazon
1
OpenAI (training)
1
Resources