# @tomjs/vite-plugin-vscode

> Use vue/react to develop 'vscode extension webview', supporting esm/cjs

Latest version **8.0.0** (published 2026-08-29) · MIT license · 0 weekly downloads

## Install

```sh
npm install @tomjs/vite-plugin-vscode
pnpm add @tomjs/vite-plugin-vscode
yarn add @tomjs/vite-plugin-vscode
bun add @tomjs/vite-plugin-vscode
```

## Health

**Score 65/100 (B)** — status: active.

Positive: has types; esm support; no vulnerabilities; recently updated; high maintenance score.

Warnings: low downloads.

## Facts

| | |
|---|---|
| Version | 8.0.0 |
| Published | 2026-08-29 |
| First published | 2023-12-19 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | bundled |
| Module format | ESM |
| Node | >=18.19 |
| Dependencies | 5 |
| Unpacked size | 71.5 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| GitHub stars | 93 |
| Author | Tom Gao |
| Maintainers | tomgao365 |
| Keywords | vite, plugin, vscode, html, hmr, extension, webview, esm, cjs |

## Links

- npm: https://www.npmjs.com/package/@tomjs/vite-plugin-vscode
- Repository: https://github.com/tomjs/vite-plugin-vscode
- Homepage: https://github.com/tomjs/vite-plugin-vscode#readme
- Issues: https://github.com/tomjs/vite-plugin-vscode/issues
- npm.io page: https://npm.io/package/@tomjs/vite-plugin-vscode

## Dependencies (5)

- [execa](https://npm.io/package/execa.md) ^9.6.1
- [picocolors](https://npm.io/package/picocolors.md) ^1.1.1
- [@tomjs/node](https://npm.io/package/@tomjs/node.md) ^2.2.3
- [lodash.merge](https://npm.io/package/lodash.merge.md) ^4.6.2
- [node-html-parser](https://npm.io/package/node-html-parser.md) ^7.1.0

## Alternatives

- [@tsparticles/shape-image](https://npm.io/package/@tsparticles/shape-image.md) — 303.7K weekly downloads
- [@tsparticles/shape-line](https://npm.io/package/@tsparticles/shape-line.md) — 233.7K weekly downloads
- [stringify-attributes](https://npm.io/package/stringify-attributes.md) — 58.6K weekly downloads
- [mobile-drag-drop](https://npm.io/package/mobile-drag-drop.md) — 46.3K weekly downloads
- [@comunica/actor-rdf-parse-html](https://npm.io/package/@comunica/actor-rdf-parse-html.md) — 29.2K weekly downloads

## Recent versions

- 8.0.0 (latest) — 2026-08-29
- 7.1.1 — 2026-01-23
- 7.1.0 — 2026-01-19
- 7.0.0 — 2026-01-11
- 6.2.0 — 2026-01-11
- 6.1.0 — 2026-01-03
- 6.0.2 — 2026-01-02
- 6.0.1 — 2025-12-29
- 6.0.0 — 2025-12-29
- 5.2.1 — 2025-12-29
- 5.2.0 — 2025-12-21
- 5.1.0 — 2025-11-29
- 5.0.0 — 2025-07-29
- 4.3.0 — 2025-07-23
- 4.2.1 — 2025-05-11
- … 32 more at https://npm.io/package/@tomjs/vite-plugin-vscode/versions

## README

# @tomjs/vite-plugin-vscode

[![npm](https://img.shields.io/npm/v/@tomjs/vite-plugin-vscode)](https://www.npmjs.com/package/@tomjs/vite-plugin-vscode) ![node-current (scoped)](https://img.shields.io/node/v/@tomjs/vite-plugin-vscode) ![NPM](https://img.shields.io/npm/l/@tomjs/vite-plugin-vscode) [![jsDocs.io](https://img.shields.io/badge/jsDocs.io-reference-blue)](https://www.jsdocs.io/package/@tomjs/vite-plugin-vscode)

**English** | [中文](./README.zh_CN.md)

> Use `vue`/`react` to develop [vscode extension webview](https://code.visualstudio.com/api/references/vscode-api#WebviewPanel), supporting `esm` and `cjs`.

During development, inject code into both `vscode extension code` and `web page` code to support `HMR`; during production builds, inject the final generated `index.html` code into the `vscode extension code` to minimize manual effort.

## Features

- Use [vite](https://vite.dev/) to quickly build `extension code`
- Simple configuration, focus on business
- Support `esm` and `cjs`
- Support ESM extension (vscode `v1.100.0+`)
- Support webview `HMR`
- Support `acquireVsCodeApi` of [@types/vscode-webview](https://www.npmjs.com/package/@types/vscode-webview)
- Support [Multi-Page App](https://vitejs.dev/guide/build.html#multi-page-app)
- Supports `vue` and `react` and other [frameworks](https://cn.vitejs.dev/guide/#trying-vite-online) supported by `vite`

### ESM extension

The NodeJS extension host now (`v1.100.0+`) supports extensions that use JavaScript-modules (ESM). All it needs is the `"type": "module"` entry in your extension's `package.json` file. With that, the JavaScript code can use `import` and `export` statements, including the special module `import('vscode')`.

## Install

```bash
# pnpm
pnpm add @tomjs/vite-plugin-vscode -D

# yarn
yarn add @tomjs/vite-plugin-vscode -D

# npm
npm i @tomjs/vite-plugin-vscode -D
```

## Usage

### Recommended

Setting `recommended` will modify some preset configurations. See [PluginOptions](#pluginoptions) and `recommended` parameter descriptions in detail.

#### Directory Structure

- By default, `recommended:true` will be based on the following directory structure as a convention.

```
|--extension      // extension code
|  |--index.ts
|--src            // front-end code
|  |--App.vue
|  |--main.ts
|--index.html
```

- Zero configuration, default dist output directory

```
|--dist
|  |--extension
|  |  |--index.js
|  |  |--index.js.map
|  |--webview
|  |  |--index.html
```

- If you want to modify the `extension` source code directory to `src`, you can set `{ extension: { entry: 'src/index.ts' } }`

```
|--src            // extension code
|  |--index.ts
|--webview        // front-end code
|  |--App.vue
|  |--main.ts
|--index.html
```

### extension

code snippet, more code see examples

```ts
import { getWebviewHtml } from 'virtual:vscode';

const panel = window.createWebviewPanel('showHelloWorld', 'Hello World', ViewColumn.One, {
  enableScripts: true,
  localResourceRoots: [Uri.joinPath(extensionUri, 'dist/webview')],
});

// Vite development mode and production mode inject different webview codes to reduce development work
panel.webview.html = getWebviewHtml({
  // vite dev mode
  serverUrl: process.env.VITE_DEV_SERVER_URL,
  // vite prod mode
  webview,
  context,
  inputName: 'index',
  injectCode: `<script>window.__FLAG1__=666;window.__FLAG2__=888;</script>`,
});
```

- Add `"@tomjs/vite-plugin-vscode/types"` to `tsconfig.node.json` or `*.d.ts` file.

`tsconfig.node.json`

```json
{
  "extends": "@tomjs/tsconfig/node.json",
  "compilerOptions": {
    "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
    "types": [
      "@tomjs/vite-plugin-vscode/types"
    ]
  },
  "include": [
    "extension",
    "*.config.ts"
  ]
}
```

`*.dt.s`

```ts
/// <reference types="@tomjs/vite-plugin-vscode/types" />
```

- `package.json`

```json
{
  "main": "dist/extension/index.js"
}
```

### vue

- `vite.config.ts`

```ts
import vscode from '@tomjs/vite-plugin-vscode';
import vue from '@vitejs/plugin-vue';
import { defineConfig } from 'vite';

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [
    vue({
      template: {
        compilerOptions: {
          isCustomElement: (tag: string) => tag.startsWith('vscode-'),
        },
      },
    }),
    vscode(),
    // Modify the extension source code entry path, and also modify the `index.html` entry file path
    // vscode({ extension: { entry: 'src/index.ts' } }),
  ],
});
```

### react

- `vite.config.ts`

```ts
import vscode from '@tomjs/vite-plugin-vscode';
import react from '@vitejs/plugin-react-swc';
import { defineConfig } from 'vite';

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [react(), vscode()],
});
```

### **getWebviewHtml**

See [vue-import](./examples/vue-import) example

- `vite.config.ts`

```ts
import path from 'node:path';
import vscode from '@tomjs/vite-plugin-vscode';
import { defineConfig } from 'vite';

export default defineConfig({
  plugins: [vscode()],
  build: {
    rollupOptions: {
      // https://cn.vitejs.dev/guide/build.html#multi-page-app
      input: [path.resolve(__dirname, 'index.html'), path.resolve(__dirname, 'index2.html')],
      // You can also customize the name
      // input:{
      //   'index': path.resolve(__dirname, 'index.html'),
      //   'index2': path.resolve(__dirname, 'index2.html'),
      // }
    },
  },
});
```

- page one

```ts
import { getWebviewHtml } from 'virtual:vscode';

getWebviewHtml({
  // vite dev mode
  serverUrl: process.env.VITE_DEV_SERVER_URL,
  // vite prod mode
  webview,
  context,
});
```

- page two

```ts
import { getWebviewHtml } from 'virtual:vscode';

getWebviewHtml({
  // vite dev mode
  serverUrl: `${process.env.VITE_DEV_SERVER_URL}/index2.html`,
  // vite prod mode
  webview,
  context,
  inputName: 'index2',
});
```

- A single page uses different parameters to achieve different functions

```ts
import { getWebviewHtml } from 'virtual:vscode';

getWebviewHtml({
  // vite dev mode
  serverUrl: `${process.env.VITE_DEV_SERVER_URL}?id=666`,
  // vite prod mode
  webview,
  context,
  injectCode: `<script>window.__id__=666;</script>`,
});
```

**getWebviewHtml** Description

```ts
interface WebviewHtmlOptions {
  /**
   * `[vite serve]` The url of the vite dev server. Please use `process.env.VITE_DEV_SERVER_URL`
   */
  serverUrl?: string;
  /**
   * `[vite build]` The Webview instance of the extension.
   */
  webview: Webview;
  /**
   * `[vite build]` The ExtensionContext instance of the extension.
   */
  context: ExtensionContext;
  /**
   * `[vite build]` vite build.rollupOptions.input name. Default is `index`.
   */
  inputName?: string;
  /**
   * `[vite build]` Inject code into the afterbegin of the head element.
   */
  injectCode?: string;
}
```

### Warning

When using the `acquireVsCodeApi().getState()` method of [@types/vscode-webview](https://www.npmjs.com/package/@types/vscode-webview), you must use `await` to call it. Since `acquireVsCodeApi` is a simulated implementation of this method by the plugin, it is inconsistent with the original method. I am very sorry. If you have other solutions, please share them. Thank you very much.

```ts
const value = await acquireVsCodeApi().getState();
```

## Parameters

### PluginOptions

| Property    | Type                                         | Default | Description                                                                                                                                                                                                                       |
| ----------- | -------------------------------------------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| recommended | `boolean`                                    | `true`  | This option is intended to provide recommended default parameters and behavior.                                                                                                                                                   |
| extension   | [ExtensionOptions](#ExtensionOptions)        |         | Configuration options for the vscode extension.                                                                                                                                                                                   |
| webview     | `boolean` \| [WebviewOption](#WebviewOption) | `true`  | Inject html code                                                                                                                                                                                                                  |
| devtools    | `boolean` \| `number`                        | `false` | Inject script code is used for debugging in [react-devtools](https://github.com/facebook/react/tree/main/packages/react-devtools) or [vue-devtools](https://devtools.vuejs.org/guide/standalone), and the port can be customized. |

#### Notice

The `recommended` option is used to set the default configuration and behavior, which can be used with almost zero configuration. The default is `true`. If you want to customize the configuration, set it to `false`. The following default prerequisites are to use the recommended [project structure](#directory-structure).

- The output directory is based on the `build.outDir` parameter of `vite`, and outputs `extension` and `src` to `dist/extension` and `dist/webview` respectively.
- Other behaviors to be implemented

#### devtools

During development, support standalone development tool applications for `react` and `vue`, enabled by default.

- `react`: inject `<script src="http://localhost:8097"></script>`, support [react-devtools](https://github.com/facebook/react/tree/main/packages/react-devtools)
- `vue`: inject `<script src="http://localhost:8098"></script>`, support [vue-devtools](https://devtools.vuejs.org/guide/standalone)

### ExtensionOptions

Based on [UserConfig](https://vite.dev/config/) of [vite](https://vite.dev), some default values are added for ease of use.

| Property    | Type                                        | Default                                         | Description                                                                                               |
| ----------- | ------------------------------------------- | ----------------------------------------------- | --------------------------------------------------------------------------------------------------------- |
| entry       | `string \| string[] \| Record`              | `extension/index.ts`                            | The vscode extension entry file.                                                                          |
| format      | `'cjs' \| 'esm'`                            | `-`                                             | The bundle format. If not specified, it will use the `type` field from `package.json`.                    |
| outDir      | `string`                                    | `dist/extension`                                | The output directory for the vscode extension file.                                                       |
| target      | `string \| string[] \| false`               | `'node20'` (esm) / `['es2019', 'node14']` (cjs) | The build target, passed to Vite's `build.target`.                                                        |
| sourcemap   | `boolean \| 'inline' \| 'hidden'`           | `true` (dev) / `false` (prod)                   | Whether to generate sourcemaps.                                                                           |
| minify      | `boolean \| 'oxc' \| 'terser' \| 'esbuild'` | `false` (dev) / `true` (prod)                   | Minify the output.                                                                                        |
| clean       | `boolean`                                   | `true`                                          | Empty the output directory before building.                                                               |
| treeshake   | `boolean`                                   | `true` (prod) / `false` (dev)                   | Enable/disable tree-shaking.                                                                              |
| external    | `Arrayable<string \| RegExp> \| function`   | `['vscode']`                                    | Don't bundle these modules. `vscode` and Node.js built-ins are always excluded.                           |
| watchFiles  | `string \| string[]`                        | ``                                              | Additional files or folders to watch during development. Vite always watches the module dependency graph. |
| ignoreWatch | `Arrayable<string \| RegExp>`               | `'.history', '.temp', '.tmp', '.cache', 'dist'` | Ignore files or folders being watched.                                                                    |
| onSuccess   | `string \| function`                        | ``                                              | A shell command or callback to run after every successful build.                                          |

Any other top-level [Vite UserConfig](https://vite.dev/config/) option (`resolve`, `define`, `plugins`, ...) can also be passed directly.

### WebviewOption

| Property | Type     | Default                                                                                                                                                          | Description                    |
| -------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------ |
| csp      | `string` | `<meta http-equiv="Content-Security-Policy" content="default-src 'none'; style-src {{cspSource}} 'unsafe-inline'; script-src 'nonce-{{nonce}}' 'unsafe-eval';">` | The `CSP` meta for the webview |

- `{{cspSource}}`: [webview.cspSource](https://code.visualstudio.com/api/references/vscode-api#Webview)
- `{{nonce}}`: uuid

### Additional Information

- Default values for `extension` when the relevant parameters are not configured

| Parameter | Development Mode Default | Production Mode Default |
| --------- | ------------------------ | ----------------------- |
| sourcemap | `true`                   | `false`                 |
| minify    | `false`                  | `true`                  |

## Environment Variables

### Vite plugin variables

`vscode extension` use.

- `development` mode

| Variable              | Description                    |
| --------------------- | ------------------------------ |
| `VITE_DEV_SERVER_URL` | The url of the vite dev server |

- `production` mode

| Variable            | Description                   |
| ------------------- | ----------------------------- |
| `VITE_WEBVIEW_DIST` | vite webview page output path |

## Debug

Run `Debug Extension` through `vscode` to debug. For debugging tools, refer to [Official Documentation](https://code.visualstudio.com/docs/editor/debugging)

`launch.json` is configured as follows:

```json
{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Debug Extension",
      "type": "extensionHost",
      "request": "launch",
      "args": ["--extensionDevelopmentPath=${workspaceFolder}"],
      "outFiles": ["${workspaceFolder}/dist/extension/*.js"],
      "preLaunchTask": "npm: dev"
    },
    {
      "name": "Preview Extension",
      "type": "extensionHost",
      "request": "launch",
      "args": ["--extensionDevelopmentPath=${workspaceFolder}"],
      "outFiles": ["${workspaceFolder}/dist/extension/*.js"],
      "preLaunchTask": "npm: build"
    }
  ]
}
```

`tasks.json` is configured as follows:

```json
{
  "version": "2.0.0",
  "tasks": [
    {
      "type": "npm",
      "script": "dev",
      "problemMatcher": {
        "owner": "typescript",
        "fileLocation": "relative",
        "pattern": {
          "regexp": "^([a-zA-Z]\\:/?([\\w\\-]/?)+\\.\\w+):(\\d+):(\\d+): (ERROR|WARNING)\\: (.*)$",
          "file": 1,
          "line": 3,
          "column": 4,
          "code": 5,
          "message": 6
        },
        "background": {
          "activeOnStart": true,
          "beginsPattern": "^.*extension build start*$",
          "endsPattern": "^.*extension build success.*$"
        }
      },
      "isBackground": true,
      "presentation": {
        "reveal": "never"
      },
      "group": {
        "kind": "build",
        "isDefault": true
      }
    },
    {
      "type": "npm",
      "script": "build",
      "group": {
        "kind": "build",
        "isDefault": true
      },
      "problemMatcher": []
    }
  ]
}
```

### Webpage Debugging

- You can use the standalone applications of [react-devtools](https://github.com/facebook/react/tree/main/packages/react-devtools) and [vue-devtools](https://devtools.vuejs.org/guide/standalone) to debug `webview`.
- For Vue projects, you can use the [vite-plugin-vue-devtools](https://devtools.vuejs.org/guide/vite-plugin) Vite plugin.

## Examples

First execute the following command to install dependencies and generate library files:

```bash
pnpm install
pnpm build
```

Open the [examples](./examples) directory, there are `vue` and `react` examples.

- [react](./examples/react): Simple react example.
- [vue](./examples/vue): Simple vue example.
- [vue-esm](./examples/vue-esm): Simple vue (ESM Extension) example.
- [vue-import](./examples/vue-import): Dynamic import() and multi-page examples.

## Related

- [@tomjs/vscode](https://npmjs.com/package/@tomjs/vscode): Some utilities to simplify the development of [VSCode Extensions](https://marketplace.visualstudio.com/VSCode).
- [@tomjs/vscode-dev](https://npmjs.com/package/@tomjs/vscode-dev): Some development tools to simplify the development of [vscode extensions](https://marketplace.visualstudio.com/VSCode).
- [@tomjs/vscode-webview](https://npmjs.com/package/@tomjs/vscode-webview): Optimize the `postMessage` issue between `webview` page and [vscode extensions](https://marketplace.visualstudio.com/VSCode)

## Important Notes

### Latest (Vite 8)

**Breaking Updates:**

- Requires **Vite `^8.0.0`**. The consumer's `extension` code is now compiled with Vite itself (Rolldown-based), instead of `tsdown`.
- `ExtensionOptions` is now based on Vite's [UserConfig](https://vite.dev/config/) instead of tsdown's options. Any top-level Vite option (`resolve`, `define`, `plugins`, ...) can be passed directly.
- The module dependency graph of the extension is always watched in dev mode; `watchFiles` is only needed for files outside the graph.
- `__dirname` / `__filename` are injected automatically for `esm` output (like the previous `shims` behavior).

### v7.0.0

Change the default value of the parameter `devtools` to `false`.

### v6.0.0

**Breaking Updates:**

Change the global `__getWebviewHtml__` method to a virtual module method called `import { getWebviewHtml } from 'virtual:vscode';`.

before:

```ts
__getWebviewHtml__({
  // vite 开发模式
  serverUrl: process.env.VITE_DEV_SERVER_URL,
  // vite 生产模式
  webview,
  context,
});
```

after：

```ts
import { getWebviewHtml } from 'virtual:vscode';

getWebviewHtml({
  // vite 开发模式
  serverUrl: process.env.VITE_DEV_SERVER_URL,
  // vite 生产模式
  webview,
  context,
});
```

### v5.0.0

**Breaking Updates:**

- Using [tsdown](https://tsdown.dev/zh-CN) instead of [tsup](https://tsup.egoist.dev/), the vscode extension [extension](#ExtensionOptions) configuration is changed to inherit [tsdown](https://tsdown.dev/zh-CN).

### v4.0.0

**Breaking Updates:**

- Merge the `__getWebviewHtml__` method for development and production into one, see [getWebviewHtml](#getwebviewhtml)

### v3.0.0

**Breaking Updates:**

- The simulated `acquireVsCodeApi` is consistent with the `acquireVsCodeApi` of [@types/vscode-webview](https://www.npmjs.com/package/@types/vscode-webview), and `sessionStorage.getItem` and `sessionStorage.setItem` are used to implement `getState` and `setState`.

---
_Source: https://npm.io/package/@tomjs/vite-plugin-vscode · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
