<script setup> all work without extra bundler wiring.
When Vue is a good fit
- You already ship production Vue apps.
- You prefer Vue single-file component authoring with scoped styles and the Composition API.
- You want extension UI surfaces that mirror existing Vue architecture.
Template examples
new-vue

extension-js/examples/newtab-vue
content-vue

extension-js/examples/content-vue
Usage with an existing extension
Add Vue to an existing extension with the steps below.Installation
Install the required dependencies:vue-loader or @vue/compiler-sfc is missing, the build error names the exact version that matches the bundled toolchain. The install command in the error is phrased for the package manager that your project uses.
Configuration
Extension.js expects Vue components in.vue files. It configures vue-loader, VueLoaderPlugin, and Vue-related define flags in the Rspack pipeline. JSX and TSX pages in a Vue project compile through vue/jsx-runtime.
Development behavior
When Extension.js detects Vue, it:- Enables
.vuecompilation in the framework plugin. - Applies Vue runtime aliases (for consistent runtime resolution).
- Supports content script updates by remounting after relevant Vue SFC changes.
Troubleshooting
- Missing Vue tooling warning: Install
vue-loaderand@vue/compiler-sfc. - Prompt to restart after install: Stop and rerun
extension devso Extension.js can load the newly installed loader/plugin. - Unexpected
.vuehandling issues: Verifyvueis present in project dependencies so Extension.js detects Vue integration.
Usage examples
In a new tab extension
To use Vue in a new tab extension, include your entry file in HTML:In a content_script file
For content scripts, mount a Vue app into an injected root node:
Best practices
- Keep UI entrypoints framework-first (
main.ts,App.vue) and keep extension APIs in dedicated modules. - Use scoped styles in SFCs when possible to reduce style leaks in extension pages.
- For large UIs, split components and shared composables to keep content scripts small.
Runtime build and the Options API
From 4.1.19, a Vue project bundles the runtime-only build,vue.runtime.esm-bundler.js, the file that the vue package names as its module entry. Extension.js aliases vue$, @vue/runtime-dom, @vue/runtime-core, and @vue/shared to that build, so your app and any transpiled workspace dependency share one Vue instance. The full build ships the template compiler, which an extension CSP cannot run, and its innerHTML and Function calls fail the addons.mozilla.org store check.
The runtime build has no template compiler, so templates must be precompiled. Single-file components give you that: vue-loader compiles each <template> at build time. In-DOM templates and string template: options are not supported. Vue warns in the console and renders nothing for such a component.
To keep runtime compilation, alias vue$ to the full build in extension.config.js:
extension.config.js
new Function, which needs unsafe-eval in the extension CSP. Manifest V3 extension pages forbid it, so the alias only helps a Manifest V2 project.
The Options API stays on in production. Extension.js sets __VUE_OPTIONS_API__ to true in every mode, so a component written with data(), methods, or computed works in the shipped bundle. __VUE_PROD_DEVTOOLS__ and hydration mismatch details are off in production.
One more define applies to every bundle, for every framework. The free identifier global is defined as globalThis, and Rspack’s own global helper is off. That helper falls back to Function("return this"), which fails the addons.mozilla.org store check, so no such shim reaches your bundle.
Next steps
- Learn more about TypeScript support.
- Explore Sass and Sass modules.

