English | 中文
Use
vue
/react
to develop vscode extension webview, supportingesm
andcjs
.
In development mode, inject the same code of @tomjs/vscode-extension-webview into vscode extension code
and web page code
, use To support HMR
; during production build, the final generated index.html
code is injected into vscode extension code
to reduce the workload.
- Use tsup to quickly build
extension code
- Simple configuration, focus on business
- Support
esm
andcjs
- Support webview
HMR
- Support
acquireVsCodeApi
of @types/vscode-webview - Support Multi-Page App
- Supports
vue
andreact
and other frameworks supported byvite
# pnpm
pnpm add @tomjs/vite-plugin-vscode -D
# yarn
yarn add @tomjs/vite-plugin-vscode -D
# npm
npm i @tomjs/vite-plugin-vscode -D
Setting recommended
will modify some preset configurations. See PluginOptions and recommended
parameter descriptions in detail.
- 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 tosrc
, you can set{ extension: { entry: 'src/index.ts' } }
|--src // extension code
| |--index.ts
|--webview // front-end code
| |--App.vue
| |--main.ts
|--index.html
code snippet, more code see examples
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 = process.env.VITE_DEV_SERVER_URL
? __getWebviewHtml__(process.env.VITE_DEV_SERVER_URL)
: __getWebviewHtml__(webview, context);
package.json
{
"main": "dist/extension/index.js"
}
vite.config.ts
import { defineConfig } from 'vite';
import vscode from '@tomjs/vite-plugin-vscode';
import vue from '@vitejs/plugin-vue';
// 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' } }),
],
});
vite.config.ts
import { defineConfig } from 'vite';
import vscode from '@tomjs/vite-plugin-vscode';
import react from '@vitejs/plugin-react-swc';
// https://vitejs.dev/config/
export default defineConfig({
plugins: [react(), vscode()],
});
See vue-import example
vite.config.ts
import path from 'node:path';
import vscode from '@tomjs/vite-plugin-vscode';
export default defineConfig({
build: {
plugins: [vscode()]
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
process.env.VITE_DEV_SERVER_URL
? __getWebviewHtml__(process.env.VITE_DEV_SERVER_URL)
: __getWebviewHtml__(webview, context);
- page two
process.env.VITE_DEV_SERVER_URL
? __getWebviewHtml__(`${process.env.VITE_DEV_SERVER_URL}/index2.html`)
: __getWebviewHtml__(webview, context, 'index2');
getWebviewHtml Description
/**
* `[vite serve]` Gets the html of webview in development mode.
* @param options serverUrl: The url of the vite dev server.
*/
function __getWebviewHtml__(options?: string | { serverUrl: string }): string;
/**
* `[vite build]` Gets the html of webview in production mode.
* @param webview The WebviewPanel instance of the extension.
* @param context The ExtensionContext instance of the extension.
* @param inputName vite build.rollupOptions.input name. Default is `index`.
*/
function __getWebviewHtml__(
webview: Webview,
context: ExtensionContext,
inputName?: string,
): string;
When using the acquireVsCodeApi().getState()
method of @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.
const value = await acquireVsCodeApi().getState();
- index.d.ts provided by unpkg.com.
Property | Type | Default | Description |
---|---|---|---|
recommended | boolean |
true |
This option is intended to provide recommended default parameters and behavior. |
extension | ExtensionOptions | Configuration options for the vscode extension. | |
webview | boolean | string | WebviewOption |
__getWebviewHtml__ |
Inject html code |
devtools | boolean |
true |
Inject script code for react-devtools or vue-devtools debugging |
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.
- The output directory is based on the
build.outDir
parameter ofvite
, and outputsextension
andsrc
todist/extension
anddist/webview
respectively. - Other behaviors to be implemented
Inject @tomjs/vscode-extension-webview into vscode extension code and web client code, so that webview
can support HMR
during the development stage.
- vite serve
- extension: Inject
import __getWebviewHtml__ from '@tomjs/vscode-extension-webview';
above the file that calls the__getWebviewHtml__
method - web: Add
<script>
tag to index.html and inject@tomjs/vscode-extension-webview/client
code
- extension: Inject
- vite build
- extension: Inject
import __getWebviewHtml__ from '@tomjs/vite-plugin-vscode-inject';
above the file that calls the__getWebviewHtml__
method If is string, will set inject method name. Default is__getWebviewHtml__
.
- extension: Inject
During development, support standalone development tool applications for react
and vue
, enabled by default.
react
: inject<script src="http://localhost:8097"></script>
, support react-devtoolsvue
: inject<script src="http://localhost:8098"></script>
, support vue-devtools
Based on Options of tsup, some default values are added for ease of use.
Property | Type | Default | Description |
---|---|---|---|
entry | string |
extension/index.ts |
The vscode extension entry file. |
outDir | string |
dist-extension/main |
The output directory for the vscode extension file |
onSuccess | () => Promise<void | undefined | (() => void | Promise<void>)> |
undefined |
A function that will be executed after the build succeeds. |
Property | Type | Default | Description |
---|---|---|---|
name | string |
__getWebviewHtml__ |
The inject method name |
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{{nonce}}
: uuid
- Default values for
extension
when the relevant parameters are not configured
Parameter | Development Mode Default | Production Mode Default |
---|---|---|
sourcemap | true |
false |
minify | false |
true |
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 |
Run Debug Extension
through vscode
to debug. For debugging tools, refer to Official Documentation
launch.json
is configured as follows:
{
"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:
{
"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|rebuild) success.*$"
}
},
"isBackground": true,
"presentation": {
"reveal": "never"
},
"group": {
"kind": "build",
"isDefault": true
}
},
{
"type": "npm",
"script": "build",
"group": {
"kind": "build",
"isDefault": true
},
"problemMatcher": []
}
]
}
First execute the following command to install dependencies and generate library files:
pnpm install
pnpm build
Open the examples directory, there are vue
and react
examples.
- react: Simple react example.
- vue: Simple vue example.
- vue-import: Dynamic import() and multi-page examples.
- @tomjs/vscode: Some utilities to simplify the development of VSCode Extensions.
- @tomjs/vscode-dev: Some development tools to simplify the development of vscode extensions.
- @tomjs/vscode-webview: Optimize the
postMessage
issue betweenwebview
page and vscode extensions
Breaking Updates:
- The simulated
acquireVsCodeApi
is consistent with theacquireVsCodeApi
of @types/vscode-webview, andsessionStorage.getItem
andsessionStorage.setItem
are used to implementgetState
andsetState
.