作为曾经最受欢迎的编辑器,VS Code 的核心优势不仅体现在其原生功能的完备性,更源于其极为丰富的扩展生态系统。无论是基础的代码格式化、智能语法提示,还是针对特定开发场景的工具集成,扩展都能让 VS Code 突破原生能力边界,实现按需 "进化"。即便如今 AI 编辑器层出不穷,其中多数仍以 VS Code 内核为基础开发,扩展的作用依旧无可替代。
因此,本文将介绍如何从零开始开发一款属于自己的 VSCode 扩展。
前言 - 什么是 VSCode 扩展
如下是摘自 VS Code 官网的一段话,大致意思就是:
VS Code 在设计之初 就考虑到了可扩展性,从用户界面(UI)到编辑体验,VS Code 几乎所有功能模块都能通过扩展 API(Extension API)进行定制与增强。而且 VS Code 的诸多核心功能本身也是以扩展形式开发的,且同样基于这套扩展 API 实现。
Visual Studio Code is built with extensibility in mind. From the UI to the editing experience, almost every part of VS Code can be customized and enhanced through the Extension API. In fact, many core features of VS Code are built as extensions and use the same Extension API.
所以简单来说,VSCode 扩展是基于 VSCode 扩展 API 开发,用于扩展或定制 VSCode 编辑器功能的组件。
一、开发环境准备
- 安装 Node.js (建议版本 16+)
由于 VS Code 是基于 Electron 框架 开发的桌面应用,依赖于 Node.js 环境,所以在开发 VS Code 扩展之前要确保您已安装 Node.js。
可在Node 官网 下载并安装,安装完成后执行如下命令确认安装是否成功:
bash
node -v
- 安装 git
可在git 官网下载安装,主要用于扩展开发过程中的版本控制。
二、项目搭建
VS Code 官方提供了专门用于搭建扩展项目的脚手架: Yeoman 和 VS Code Extension Generator。
- 如果你不希望安装 Yeoman 和 VS Code Extension Generator,请在终端执行如下命令:
bash
npx --package yo --package generator-code -- yo code
- 如果您想全局安装 Yeoman 以方便重复运行,请在终端执行以下命令:
bash
npm install --global yo generator-code
yo code
命令执行后会出现如下选项:
- What type of extension do you want to create? :New Extension (TypeScript)
- What's the name of your extension? :扩展名称(比如 hello-world-extension)。
- What's the identifier of your extension? :扩展唯一标识(默认与名称一致即可)。
- What's the description of your extension? :扩展描述(比如 My first VSCode extension)。
- Initialize a git repository? :是否初始化 Git 仓库(选 No 也可以,后续自己手动初始化)。
- Which bundler to use? :使用哪个打包工具(建议选 webpack)。
- Which package manager to use? :使用哪个包管理工具(建议选 pnpm)

所有选项配置完成后,待相关依赖下载安装完毕,扩展项目便搭建完成。接下来,用 VSCode 打开该项目文件夹,其结构如下
dart
hello-world-extension/
├── .vscode
│ ├── launch.json // Config for launching and debugging the extension
│ └── tasks.json // Config for build task that compiles TypeScript
├── .gitignore // Ignore build output and node_modules
├── README.md // Readable description of your extension's functionality
├── src
│ └── extension.ts // Extension source code
├── package.json // Extension manifest
├── tsconfig.json // TypeScript configuration
其中最关键的两个文件:package.json 和 extension.ts。
(1)package.json ------ 扩展清单
该文件是扩展的核心配置,VSCode 通过它识别扩展的功能。关键配置项如下:
json
{
"name": "hello-world-plugin",
"displayName": "Hello World Plugin",
"version": "0.0.1",
"engines": {
"vscode": "^1.80.0" // 扩展支持的 VSCode 最低版本
},
"activationEvents": [ // 激活事件:当用户执行 "hello-world-plugin.helloWorld" 命令时激活
"onCommand:hello-world-plugin.helloWorld"
],
"contributes": { // 贡献点:向 VSCode 注册命令
"commands": [{
"command": "hello-world-plugin.helloWorld", // 命令唯一标识
"title": "Hello World" // 命令在命令面板中的显示名称
}]
},
"main": "./out/extension.js", // 扩展编译后的入口文件(TypeScript 编译后输出到 out 文件夹)
"scripts": {
"vscode:prepublish": "npm run compile", // 发布前执行的命令(编译 TypeScript)
"compile": "tsc -p ./", // 编译 TypeScript 命令
"watch": "tsc -watch -p ./", // 监听文件变化,自动编译
"pretest": "npm run compile && npm run lint",
"lint": "eslint src --ext ts",
"test": "node ./out/test/runTest.js"
}
}
(2)extension.ts ------ 入口文件
该文件文件导出了两个函数:activate
和 deactivate
。activate
会在已注册的激活事件发生时执行。deactivate
会让你在扩展停用前有机会进行清理。默认生成代码如下:
javascript
// 导入 vscode 模块,获取 VSCode API
import * as vscode from 'vscode';
// 扩展激活时执行的函数(激活事件触发后调用)
export function activate(context: vscode.ExtensionContext) {
// 注册一个命令:命令标识与 package.json 中一致
let disposable = vscode.commands.registerCommand(
'hello-world-extension.helloWorld',
() => {
// 命令执行时的逻辑:弹出信息提示框
vscode.window.showInformationMessage('Hello World!');
}
);
// 将命令注册到上下文,确保扩展卸载时能释放资源
context.subscriptions.push(disposable);
}
// 扩展卸载时执行的函数(可选,用于清理资源,比如关闭连接、删除临时文件)
export function deactivate() {}
有关 VSCode 扩展的开发流程以及相关文件的具体作用可参考如下官方文档介绍:
1\] [Your First Extension](https://link.juejin.cn?target=https%3A%2F%2Fcode.visualstudio.com%2Fapi%2Fget-started%2Fyour-first-extension "https://code.visualstudio.com/api/get-started/your-first-extension") \[2\] [Extension Anatomy](https://link.juejin.cn?target=https%3A%2F%2Fcode.visualstudio.com%2Fapi%2Fget-started%2Fextension-anatomy "https://code.visualstudio.com/api/get-started/extension-anatomy")
三、 运行与调试
我们可以通过如下步骤进行调试:
- 点击 VSCode 左侧的 运行和调试 图标(或按 Ctrl+Shift+D)。
- 点击顶部的 运行和调试 下拉框,选择 Run Extension
- 点击调试按钮(或F5)启动调试,会自动打开一个新的 VSCode 窗口(即 "扩展开发宿主" 窗口)。

- 然后在新窗口中,按
Ctrl+Shift+P
打开命令面板,输入并选择 Hello World 命令。 - 此时窗口右下角会弹出 Hello World from hello-world-extension! 的提示框 ------ 恭喜!你的第一个扩展运行成功了!
四、打包与发布
扩展开发完成后,可将扩展打包成 .vsix 文件,再发布到 VSCode 扩展市场,分享给其他人使用。对此 VS Code 官方提供了 vsce
工具。
vsce ( Visual Studio Code Extensions ) 是一款用于打包、发布和管理 VS Code 扩展的命令行工具
安装 vsce
bash
npm install -g @vscode/vsce
4.1 打包(packaging)
安装好 vsce 工具后,在项目根目录执行如下命令,打包生成 .vsix
文件:
bash
vsce package
打包成功后,项目根目录会生成一个 .vsix 文件(比如 hello-world-extension-0.0.1.vsix)。双击该文件,即可在 VSCode 中安装你的扩展。
4.2 发布到 VSCode 扩展市场
如果想向更多人分享你的扩展,可以发布到 VSCode 扩展市场,大致步骤如下:
- 登录到 Azure DevOps,创建自己的组织
- 获取个人访问令牌(Personal Access Token)
- 创建发布者,并验证身份
- 在项目根目录执行如下命令,将扩展发布到市场
bash
vsce publish
具体步骤详情可参考官方文档。
至此,VS Code 扩展开发的全流程就结束了。但是在实际开发场景中,若想为用户提供更灵活、更复杂的交互界面,仅依靠 VS Code 原生 API 可能无法完全满足需求,此时 Webview 就成为了关键的进阶能力。
五、Webview
Webview API 允许扩展在 VS Code 中创建完全可定制的视图,可用于构建复杂的用户界面,超出 VS Code API 的支持范围。
5.1 Webview 开发示例
如下是官方文档中给出的一个有关 Webview API 使用的示例:
js
import * as vscode from 'vscode';
export function activate(context: vscode.ExtensionContext) {
context.subscriptions.push(
vscode.commands.registerCommand('catCoding.start', () => {
// 创建并显示 Webview Panel
const panel = vscode.window.createWebviewPanel(
'catCoding', // viewType: Webview 面板的类型标识
'Cat Coding', // title: 面板的标题
vscode.ViewColumn.One, // column: 显示面板的编辑器列
{} // options: Webview 选项
);
// 设置面板的 HTML 内容
panel.webview.html = getWebviewContent();
})
);
}
function getWebviewContent() {
return `<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Cat Coding</title>
</head>
<body>
<img src="https://media.giphy.com/media/JIX9t2j0ZTN9S/giphy.gif" width="300" />
</body>
</html>`;
}
在扩展宿主窗口中,按 Ctrl+Shift+P
打开命令面板,输入并选择 Cat Coding 命令,会显示如下视图:

简单来说,可以将 webview 视为 VS Code 中由扩展控制的 iframe。webview 可以在该框架中呈现几乎任何 HTML 内容,并通过消息传递(PostMessage)与扩展进行通信。
有关如何使用 Webview API 创建自定义视图,以及 Webview 如何与扩展进行通信,可参考官方文档的介绍。
5.2 基于 React 开发 Webview
如上述所示,webview 的内容是通过 HTML 代码来定义的。但是如果直接编写原生 HTML 开发效率低且难以维护。目前前端项目通常基于 React、Vue 等框架来开发。那我们是否也可以基于这些框架来开发 webview 呢?答案是肯定的!!!
我们可以通过如下步骤在扩展项目中集成一个 React 项目,用于 webview 的开发:
1. 创建 React 子项目
在扩展项目 src
目录下创建一个 react-webview
(命名可自定义) 文件夹。
然后切换到react-webview
目录下,使用 Vite 快速创建一个 React 项目
bash
// 切换到 react-webview 目录
cd src/react-webview
// 创建 React 项目
pnpm create vite@latest . --template react-ts
//安装依赖
pnpm install
注:本文使用 Vite 创建 React 项目,使用其他脚手架或者自己搭建也可以。除了后续打包配置上有区别,大致流程差不多。
2. 修改打包配置
编辑 react-webview/vite.config.ts
,主要修改以下内容:
- 配置
build.outDir
:指定输出目录(建议放在插件项目的 dist 文件夹下,便于管理)。 - 使用 vite-plugin-style-inject 插件,将 CSS 注入 JS 文件中。(便于后续HTML代码中只需引入一个文件)
修改后的配置如下:
ts
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import styleInject from 'vite-plugin-style-inject';
export default defineConfig({
plugins: [
react(),
styleInject() // 将 CSS 直接注入到 JS 中
],
build: {
// 打包输出到插件项目的 dist/react-webview 目录
outDir: '../../dist/react-webview',
// 确保静态资源文件名稳定(避免哈希值导致路径变化)
assetsDir: 'assets',
rollupOptions: {
output: {
// 固定 chunk 文件名(可选,便于调试)
chunkFileNames: 'assets/[name].js',
entryFileNames: 'assets/[name].js',
},
},
},
});
配置修改完成后,在 react-webview
目录下运行打包命令:
bash
pnpm run build
打包完成后,插件项目根目录会生成 dist/react-webview
文件夹,包含 index.html
、assets/index.js
等文件。

3. Webview 中引入打包后的 js 文件
打包完成后,我们只需在 HTML 代码中通过<script>
标签引入打包生成的 dist/react-webview/assets/index.js
文件即可,具体代码如下:
ts
import * as vscode from 'vscode';
import * as path from 'path';
export function activate(context: vscode.ExtensionContext) {
// 1. 注册命令:触发 Webview 打开(命令名需与 package.json 匹配)
let disposable = vscode.commands.registerCommand(
'hello-world-extension.openReactWebview',
() => {
// 2. 创建 Webview 面板
const panel = vscode.window.createWebviewPanel(
'reactWebview', // Webview 唯一标识
'React Webview Demo', // 面板标题
vscode.ViewColumn.One, // 打开的列(默认第一列)
{
// 3. 配置 Webview 选项(关键:允许访问本地资源)
enableScripts: true, // 允许执行 JS
localResourceRoots: [
// 配置允许访问的本地资源路径(React 打包后的 dist 目录)
vscode.Uri.file(path.join(context.extensionPath, 'dist/react-webview'))
]
}
);
// 4. 生成 React 资源的 URI(将本地路径转为 Webview 可访问的 URI)
const fileUri = vscode.Uri.file(
path.join(context.extensionPath, 'dist/react-webview', 'assets/index.js')
);
// 关键:使用 webview.asWebviewUri() 转换路径,避免安全限制
const scriptUri = panel.webview.asWebviewUri(fileUri);
panel.webview.html = getWebviewContent(scriptUri);
}
);
context.subscriptions.push(disposable);
}
export function deactivate() { }
function getWebviewContent(scriptUri: vscode.Uri): string {
return `<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>React Webview</title>
<script type="module" crossorigin src="${scriptUri}"></script>
</head>
<body>
<div id="root"></div>
</body>
</html>`
}
需要注意的是 :HTML 代码中需要包含
<div id="root"></div>
元素,这个 React 页面的根元素。
4. 配置插件命令(package.json)
编辑插件根目录的 package.json,添加命令注册和激活事件,确保插件能被触发:
json
{
"contributes": {
"commands": [
{
"command": "hello-world-extension.openReactWebview",
"title": "Open React Webview",
"category": "Hello World Extension"
}
]
},
}
运行和调试
完成上述步骤后,即可启动插件,在命令面板中选择 Open React Webview 命令,会显示如下视图:

如上步骤所示,我们需要先打包 React 子项目打包,然后再 Webview 的 HTML 代码中引入打包生成的文件。如果 React 子项目中代码发生变化,那么每次调试之前都需要重新打包,这种开发体验是不好的。对此,我们可以通过以下方式实现开发模式下的热重载(HMR)
使用 watch
模式构建,即在执行 build
命令时添加 --watch
参数:
bash
pnpm run build --watch
注:有关如何基于 React 开发 webview,本文只是给出了大体步骤,但是具体实现细节会根据所选择的工具不同而有所差异。
但是大体思想就是将 React 项目打包成一个 js 文件,然后再 Webview 的 HTML 代码中引入这个文件。
总结
本文简单介绍了 VS Code 扩展开发全流程,同时针对复杂界面需求,补充了 Webview 基础使用及集成 React 框架的进阶方案。如有错误,欢迎大佬们指正。