# Why Your Vue JS Chrome Extension Is Not Detecting the Local Server App

> Is your Vue JS Chrome extension not detecting your local app? Learn why production builds block DevTools and how to fix it for seamless debugging. Get your Vue development back on track today.

- Repository: [Vue/core](https://github.com/vuejs/core)
- Tags: how-to-guide
- Published: 2026-02-16

---

**The Vue DevTools Chrome extension requires a development build of Vue that exposes `window.__VUE_DEVTOOLS_GLOBAL_HOOK__`, which is stripped from production builds and blocked in restricted environments.**

When developing Vue applications locally, you expect the Vue DevTools Chrome extension to automatically detect your app and display component trees. However, if your Vue JS Chrome extension is not detecting the application running on your local server, the issue typically stems from how Vue injects the global devtools hook during runtime. This handshake mechanism, implemented in the Vue core source code, serves as the bridge between your app and the browser extension.

## How Vue DevTools Detection Works

The detection process relies on a global hook injected into the page that the Chrome extension polls for. When present, the extension establishes a connection to track component trees, state changes, and performance events.

### Renderer Bootstrap in runtime-core

When a renderer is created, Vue checks environment flags `__DEV__` or `__FEATURE_PROD_DEVTOOLS__`. If either is true, it calls `setDevtoolsHook` with the global hook value found on `window` (`target.__VUE_DEVTOOLS_GLOBAL_HOOK__`).

```typescript
// packages/runtime-core/src/renderer.ts
// … line 551‑555
const target = getGlobalThis()
target.__VUE__ = true
if (__DEV__ || __FEATURE_PROD_DEVTOOLS__) {
  setDevtoolsHook(target.__VUE_DEVTOOLS_GLOBAL_HOOK__, target)
}

```

<https://github.com/vuejs/core/blob/main/packages/runtime-core/src/renderer.ts#L551-L555>

### Hook Registration and Event Buffering

The `setDevtoolsHook` function in [`packages/runtime-core/src/devtools.ts`](https://github.com/vuejs/core/blob/main/packages/runtime-core/src/devtools.ts) stores the incoming hook in a module-level variable and creates a replay buffer for events that occur before the extension injects its hook.

```typescript
// packages/runtime-core/src/devtools.ts
export function setDevtoolsHook(hook: DevtoolsHook, target: any): void {
  devtools = hook
  if (devtools) {
    devtools.enabled = true
    buffer.forEach(({ event, args }) => devtools.emit(event, ...args))
    buffer = []
  } else { /* … handle late injection … */ }
}

```

<https://github.com/vuejs/core/blob/main/packages/runtime-core/src/devtools.ts#L52-L73>

## Common Reasons Your Vue JS Chrome Extension Is Not Detecting the App

Several environmental and build factors can prevent the global hook from being established, breaking the connection between your local server and the Chrome extension.

### Production Build Restrictions

When you use [`vue.global.prod.js`](https://github.com/vuejs/core/blob/main/vue.global.prod.js) or run `vite build --mode production`, the compile-time flag `__DEV__` is set to `false` and `__FEATURE_PROD_DEVTOOLS__` is disabled. Consequently, the renderer bootstrap code that calls `setDevtoolsHook` is tree-shaken out of the bundle. Without `window.__VUE_DEVTOOLS_GLOBAL_HOOK__`, the extension cannot detect the application.

### Server-Side Rendering and Non-Browser Environments

In SSR contexts or test environments using `jsdom`, Vue explicitly guards against injecting the devtools hook. The framework checks `typeof window !== 'undefined' && window.HTMLElement && !window.navigator?.userAgent?.includes('jsdom')` before establishing the hook. If this guard fails—as it does in Node.js or simulated DOM environments—the Chrome extension remains unaware of the Vue instance.

### Content Security Policy Blocks

The Vue DevTools extension injects a script tag into the page to establish communication. A restrictive Content Security Policy header such as `script-src 'self'` blocks this inline injection, preventing the extension from registering its hook and leaving `window.__VUE_DEVTOOLS_GLOBAL_HOOK__` undefined.

### Runtime-Only Build Limitations

If you import from `@vue/runtime-core` directly instead of the full `vue` package or `vue/runtime-dom`, you bypass the DOM-specific devtools initialization. The runtime-core package lacks the browser-targeted hook registration logic found in the full build, so the extension cannot attach to your application.

## How to Enable Vue DevTools on Your Local Server

Follow these steps to ensure your local development environment exposes the necessary hook for the Chrome extension.

1. **Serve a development build.** Import Vue from the ESM browser development bundle that includes `__DEV__` flags.

   ```html
   <script type="module">
     import { createApp } from 'https://unpkg.com/vue@3/dist/vue.esm-browser.js'
     createApp({ /* ... */ }).mount('#app')
   </script>
   ```

2. **Verify Vite or webpack mode.** Ensure your bundler runs in development mode.

   ```bash
   # Vite development server (correct)

   npm run dev
   
   # Production build (devtools disabled)

   npm run build
   ```

3. **Check the global hook.** Open your browser console and verify the hook exists.

   ```javascript
   console.log('Vue DevTools hook →', window.__VUE_DEVTOOLS_GLOBAL_HOOK__)
   ```

   If this returns `undefined`, you are using a production build or a restricted environment.

4. **Adjust CSP headers.** If your local server uses strict CSP headers, temporarily relax them to allow the extension’s script injection.

   ```http
   Content-Security-Policy: script-src 'self' 'unsafe-eval' chrome-extension://*
   ```

5. **Use the full Vue package.** Ensure you are importing from `vue` rather than `@vue/runtime-core` to include DOM-specific devtools logic.

## Code Examples for Debugging Detection Issues

### Minimal HTML App That Works with DevTools

This example imports the development ESM build and logs the hook status.

```html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Vue DevTools Demo</title>
</head>
<body>
  <div id="app">{{ message }}</div>

  <script type="module">
    // Import the dev (non‑minified) build
    import { createApp } from 'https://unpkg.com/vue@3/dist/vue.esm-browser.js'

    const App = {
      data() {
        return { message: 'Hello from Vue DevTools!' }
      }
    }

    createApp(App).mount('#app')

    // Quick sanity check
    console.log('DevTools hook →', window.__VUE_DEVTOOLS_GLOBAL_HOOK__)
  </script>
</body>
</html>

```

### Vite Configuration for Development Mode

Force Vite to resolve the ESM bundler development build.

```javascript
// vite.config.js
export default {
  // No explicit mode → Vite dev server runs in development mode
  plugins: [],
  resolve: {
    alias: {
      // Force Vite to use the ESM dev build during dev
      vue: 'vue/dist/vue.esm-bundler.js'
    }
  }
}

```

Run the development server:

```bash
npm run dev   # Dev server → DevTools can detect the app

```

### Programmatic Hook Detection

Use this utility to warn when the hook is missing.

```javascript
function ensureDevtoolsHook() {
  if (!window.__VUE_DEVTOOLS_GLOBAL_HOOK__) {
    console.warn(
      'Vue DevTools hook not detected. You may be using a production build or a restricted environment.'
    )
  }
}
ensureDevtoolsHook()

```

## Summary

- The Vue DevTools Chrome extension detects applications by polling for `window.__VUE_DEVTOOLS_GLOBAL_HOOK__`, which Vue injects during renderer initialization in development builds.
- In [`packages/runtime-core/src/renderer.ts`](https://github.com/vuejs/core/blob/main/packages/runtime-core/src/renderer.ts), Vue checks `__DEV__` or `__FEATURE_PROD_DEVTOOLS__` before calling `setDevtoolsHook` to establish the global hook.
- Production builds (`vite build`, [`vue.global.prod.js`](https://github.com/vuejs/core/blob/main/vue.global.prod.js)) disable this hook injection, preventing detection.
- SSR, jsdom environments, strict CSP headers, and the runtime-only build (`@vue/runtime-core`) also block hook registration.
- To fix detection, serve the development ESM build, verify `window.__VUE_DEVTOOLS_GLOBAL_HOOK__` exists in the console, and ensure your bundler runs in development mode.

## Frequently Asked Questions

### Why does the Vue DevTools extension work on some sites but not my localhost?

Production websites often deploy minified production builds where `__DEV__` is false and `__FEATURE_PROD_DEVTOOLS__` is disabled, stripping the hook injection code from [`packages/runtime-core/src/renderer.ts`](https://github.com/vuejs/core/blob/main/packages/runtime-core/src/renderer.ts). Your localhost may also be serving a production build or using a runtime-only package that lacks the DOM-specific devtools initialization required for the Chrome extension to connect.

### How do I check if my Vue app is exposing the devtools hook?

Open your browser’s developer console on the page running your Vue app and execute `console.log(window.__VUE_DEVTOOLS_GLOBAL_HOOK__)`. If it returns an object with methods like `emit` and `on`, the hook is present and the extension should detect your app. If it returns `undefined`, you are likely using a production build or a restricted environment that prevents hook injection according to the Vue core source code.

### Can I use Vue DevTools with a production build on my local server?

By default, no. Production builds disable the devtools hook injection in [`packages/runtime-core/src/renderer.ts`](https://github.com/vuejs/core/blob/main/packages/runtime-core/src/renderer.ts) because both `__DEV__` and `__FEATURE_PROD_DEVTOOLS__` are false. However, you can enable detection in production by building Vue from source with the `__FEATURE_PROD_DEVTOOLS__` flag enabled, though this is not recommended for performance and security reasons.

### Why does the extension fail when I use `@vue/runtime-core` directly?

The `@vue/runtime-core` package contains the core reactivity and component logic but lacks the browser-specific devtools integration found in `vue/runtime-dom`. The hook registration in [`packages/runtime-core/src/renderer.ts`](https://github.com/vuejs/core/blob/main/packages/runtime-core/src/renderer.ts) relies on a global target (`window`) that is properly set up in the full browser build. Importing from `vue` or [`vue/dist/vue.esm-browser.js`](https://github.com/vuejs/core/blob/main/vue/dist/vue.esm-browser.js) ensures you receive the DOM-aware build that initializes the devtools hook correctly.