Skip to main content
Ship extension behavior across background, content scripts, and UI pages with one JavaScript/TypeScript pipeline. Extension.js collects script entrypoints from manifest.json, HTML pages, and special folders. It compiles them with the default SWC (Speedy Web Compiler)-based setup.

Template examples

javascript

javascript template screenshot Vanilla JavaScript extension with a new-tab page.
npx extension@latest create my-extension --template=javascript
Repository: extension-js/examples/javascript

content

content template screenshot Vanilla JavaScript content script injected into web pages.
npx extension@latest create my-extension --template=content
Repository: extension-js/examples/content

JavaScript capabilities

CapabilityWhat it gives you
Shared JS/TS pipelineCompile extension scripts with one default transformer setup
Entrypoint discoveryLoad script entries from manifest, pages, and special folders
Runtime-safe outputsEmit predictable script artifacts for each extension context
Path normalizationRewrite supported extension-path literals to output-safe paths

Supported script entrypoints

Manifest fieldFile type expected
background.service_worker.js, .ts, .mjs, .tsx
background.scripts.js, .ts, .mjs, .tsx
content_scripts.js.js, .ts, .mjs, .tsx
user_scripts.api_script.js, .ts, .mjs, .tsx

Sample script declaration in manifest.json

Example script declaration in manifest.json:
{
  "manifest_version": 3,
  "name": "My Extension",
  "version": "1.0.0",
  "background": {
    "service_worker": "./scripts/background.ts"
  },
  "content_scripts": [
    {
      "matches": ["<all_urls>"],
      "js": ["./scripts/content-script.ts"]
    }
  ]
}

Development behavior

  • Content scripts: Extension.js injects hot module replacement (HMR)/remount flow for fast updates.
  • Extension pages: Page scripts follow page HMR behavior.
  • Background/service worker: Script updates can trigger a hard extension reload depending on the change type.
  • Entrypoint list changes: changing manifest script structure may require a dev server restart.

Script locations and conventions

  • Use scripts/ at project root for script-centric extension entries.
  • Use pages/ for HTML entrypoints with their own scripts.
  • Keep manifest-referenced paths stable; avoid moving entry files without updating manifest.

Transform and bundling defaults

  • SWC is the default transformer for JS/TS/JSX/TSX.
  • Extension.js uses browser-first package.json field resolution (browser, module, main).
  • Extension.js emits entries predictably and does not split code into separate output files by default.
  • Path resolution rewrites static extension-path literals in supported APIs.

Dynamic import caveats

  • Content-script dynamic import has runtime constraints; Extension.js uses loader fallbacks where possible.
  • Service worker lazy-loading has browser limitations; prefer eager imports in code that must be available immediately when the service worker starts.

Best practices

  • Keep entry scripts thin and move feature logic into shared modules.
  • Prefer static import paths for extension APIs so path resolution can normalize them safely.
  • Avoid unnecessary dynamic import in content scripts and service workers.
  • Treat manifest script list edits as structural changes in development workflows.

Next steps