Skip to main content
Run extension-wide logic in background contexts with clear support for both Manifest V2 (MV2) background scripts and Manifest V3 (MV3) service workers. Extension.js reads background entries from manifest.json and compiles them into dedicated background outputs. It applies browser-specific reload behavior during development.

Template examples

action

action template screenshot An action popup extension with a background service worker handling browser events.
npx extension@latest create my-extension --template=action
Repository: extension-js/examples/action

action-chatgpt

action-chatgpt template screenshot Action popup with a background service worker that integrates with an external API (ChatGPT).
npx extension@latest create my-extension --template=action-chatgpt
Repository: extension-js/examples/action-chatgpt

Background capabilities

CapabilityWhat it gives you
MV2/MV3 compatibilitySupport background.scripts and background.service_worker entries
Dedicated background outputsEmit background runtime files per active manifest shape
Reload-aware developmentApply hard reload/restart behavior for structural changes
Worker mode controlRespect background.type module/classic runtime behavior

Background script support

Declare background scripts with these manifest.json fields:
Manifest fieldFile type expecteddev behavior
background.service_worker.js, .ts, .mjs, .tsxhard reload flow
background.scripts.js, .ts, .mjs, .tsxhot module replacement (HMR)-compatible path
background.type can also affect runtime mode (module vs classic service worker behavior).

Sample background script declaration

Example background script declaration in manifest.json:
{
  "manifest_version": 3,
  "name": "My Extension",
  "version": "1.0.0",
  "background": {
    "service_worker": "./scripts/background.ts"
  }
}

Development behavior

  • Extension.js tracks service worker/source changes and can trigger hard extension reload.
  • Manifest changes affecting background entries can trigger restart-required diagnostics.
  • Browser launch plugins apply target-specific hard reload strategies (Chromium/Firefox).
  • Extension.js treats structural entrypoint changes more strictly than regular module edits.

MV3 service worker lifecycle

background.service_worker runs under the browser’s service-worker lifecycle, not as a long-running process. That means:
  • in-memory state can disappear between events
  • design long-running work around events, not process permanence
  • startup should stay small and predictable
  • your code should restore important state from storage or recompute it safely
Use background.scripts only for MV2-style compatibility cases. For MV3-first extensions, treat the service worker as the central coordinator for browser API calls and cross-context communication.

Output behavior

Common outputs include:
  • background/service_worker.js
  • background/scripts.js
The exact output depends on which manifest field remains active after browser filtering.

Module and classic notes

  • background.type: "module" uses module worker semantics.
  • Classic service worker mode uses importScripts-based chunk loading behavior.
  • Avoid dynamic imports in background code that must load immediately on startup.
  • Keep the background entry thin and move feature logic into shared modules.
  • Use the background context as the central coordinator for messaging, storage access, and browser API calls.
  • Restore durable state from storage instead of assuming the background script stays running permanently.
  • Use alarms, explicit event listeners, and small feature modules instead of one large startup path.

Common mistakes

  • Treating the service worker like a permanently running server process.
  • Keeping critical state only in memory.
  • Doing expensive startup work on every event wakeup.
  • Putting too much feature logic in popup or content-script code when it actually needs background-level browser API access.

Best practices

  • Prefer background.service_worker for MV3-first extensions.
  • Keep background entry files small and delegate logic to shared modules.
  • Avoid expensive startup work in service workers; initialize lazily where safe.
  • Treat manifest background field edits as structural changes in dev flow.
  • Route privileged actions through validated message handlers.
  • Store durable settings and caches in browser storage, not only in module-level variables.

Next steps