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.
Repository: extension-js/examples/action

ai-chatgpt

ai-chatgpt template screenshot Action popup with a background service worker that integrates with an external API (ChatGPT).
Repository: extension-js/examples/ai-chatgpt

Background capabilities

Background script support

Declare background scripts with these manifest.json fields: background.type can also affect runtime mode (module vs classic service worker behavior).

Sample background script declaration

Example background script declaration in manifest.json:

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.

Firefox: service worker translated to an event page

Firefox does not run MV3 background.service_worker (loading such an add-on fails with “background.service_worker is currently disabled. Add background.scripts.”). You don’t need to special-case it: for the Firefox build, Extension.js automatically translates a background.service_worker entry into a background.scripts event page pointing at the same compiled bundle. Author one background.service_worker and it loads on both Chromium and Firefox.

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.

Runtime-loaded files

Some files never appear as import statements but still must ship with the extension. Extension.js traces these into the output so the built extension behaves like the source loaded unpacked in the browser:
  • importScripts(...) dependencies of classic service workers. String-literal arguments are resolved recursively (a dependency can call importScripts itself) against the emitted worker location, so worker-relative URLs keep working even though the worker moves to background/service_worker.js. WebAssembly sibling files loaded by wasm-bindgen glue (*_bg.wasm) ship alongside their loader.
  • chrome.scripting.executeScript({files: [...]}) and insertCSS({files: [...]}) payloads. Files referenced only from files: arrays (not declared in manifest content_scripts) are copied verbatim at their extension-root paths.
A referenced file that does not exist in your project produces a build warning naming the missing path, instead of a silent runtime failure.
  • 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