VS Code 正在逐渐缩小文本编辑器和集成开发环境 (IDE) 之间的差距。这款极其通用且灵活的工具的核心在于一个出色的 API,它提供了一个可扩展的插件模型,JavaScript 开发人员相对容易在其上进行构建。我的第一个扩展程序 VS Code All Autocomplete 已达到 25K 次下载量,我想与大家分享我在其开发和维护过程中学到的东西。
琐事!Visual Studio Code 与 Visual Studio IDE 没有任何血缘关系。Microsoft 使用 VS 品牌面向其企业受众,这导致了很多混淆。该应用程序在命令行中仅为 Code
,并且根本不适用于 Visual Studio。它从 TextMate 和 Sublime Text 而不是 Visual Studio 中获得了更多灵感。它共享 TextMate(仅限 Mac)的代码片段格式,并放弃了 Visual Studio 中使用的基于 XML 的格式。
为什么要创建扩展
从表面上看,VS Code 似乎没有提供太多理由让人们为其创建扩展。该平台拥有与其他编辑器相同的大多数功能。代码片段格式功能强大,并且借助 Settings Sync 等扩展程序,可以轻松地通过 Gist 共享它们。代码(双关语)是 开源的,并且团队对请求的响应相当迅速。通过在 npm 模块中创建“typings”文件,可以在没有插件的情况下提供基本支持。
尽管如此,出于以下原因,所有 Web 开发人员都应该尝试为 VS Code 创建扩展
- 使用 TypeScript:许多开发人员仍在 TypeScript 的边缘。在 VS Code 中编写扩展程序可以让您有机会亲眼见证 TypeScript 的工作原理,以及其类型安全和自动完成功能如何帮助您进行下一个 JavaScript 项目。
- 学习:Web 因其性能而受到 很多批评。VS Code 演示了如何在 Electron 中开发对性能敏感的应用程序,以及一些技术——多进程和面向集群的架构非常出色,以至于所有 Electron 应用程序都应该将其用于自身。
- 乐趣:最重要的是,开发 VS Code 扩展非常有趣。您可以解决一个难题,最终回馈社区,并为许多开发人员节省时间。
琐事!尽管 TypeScript 是一种独立的编程语言,具有许多流行的用途,包括 Angular (2+) 框架,但 VS Code 是对该语言影响最大的姊妹项目。作为 TypeScript 编辑器,VS Code 以 TypeScript 开发,与 TypeScript 存在着强大的共生关系。学习该语言的最佳方法是查看 Visual Studio Code 的源代码。
扩展程序可以做什么
VS Code 公开了多个扩展程序可以产生影响的区域。公开的接触点很容易填满一本书。但您不太可能需要所有这些接触点,因此我在这里列出了一个清单。
这些概述了截至 1.25 版本可以扩展的各个位置
区域 | 描述 |
---|---|
语言语法 | 用于突出显示的变量、表达式、保留字等。 |
代码片段 | 自动完成项,带有基于选项卡的导航以替换某些项 |
语言配置 | 自动关闭和缩进项目,如引号、括号等。 |
悬停操作项 | 悬停时的文档工具提示 |
代码完成 | 键入时自动完成项 |
错误诊断 | 波浪状红色下划线,指示潜在错误 |
签名助手 | 键入时的函数签名工具提示 |
符号定义 | 符号在内联编辑器中定义的代码位置,以及转到定义(包括 ⌘+Hover 工具提示) |
引用 | 对于内联编辑器,包含链接、所有文件和与符号关联的位置 |
文档突出显示 | 所有选定符号存在位置的列表,用于突出显示 |
符号 | 从命令菜单(使用 @ 修饰符)可导航的符号列表 |
工作区符号 | 整个工作区的符号提供程序 |
代码操作 | 波浪状绿色下划线,指示可修复的错误,单击即可修复 |
代码镜头 | 始终显示带有可单击操作项的内联元数据 |
重命名 | 支持重命名在多个位置使用的符号 |
文档格式化 | 修复整个文档的缩进和格式 |
文档范围格式化 | 修复所选文本的缩进和格式 |
键入时格式化 | 实时修复格式和缩进 |
颜色提供程序 | 颜色弹出菜单替代方案 |
配置默认值 | 覆盖设置并另存为一组新的默认值 |
命令 | ⌘+P 菜单中的命令 |
菜单 | 顶级菜单中的菜单项、文档选项卡栏旁边的任何菜单以及上下文菜单 |
键绑定 | 键盘快捷键 |
调试器 | 用于调试新语言或现有语言的调试器设置 |
源代码管理 | 覆盖以支持自定义源代码管理系统 |
主题 | 颜色主题 |
代码片段 | 与上面的代码片段相同 |
视图 | 左侧停靠面板之一中的一个新部分 |
视图容器 | 左侧栏上的一个新的停靠面板 |
TypeScript 服务器插件 | 内置 TypeScript 语言服务器的覆盖 |
Webview | 与文档并行的替代页面,用于显示文档的自定义渲染或任何自定义 HTML(与停靠在侧面的视图容器不同) |
文本装饰 | 文本区域装订线上的装饰 |
消息 | 右下角显示错误、警告和信息消息的弹出窗口 |
快速选择 | 多选选项选择器菜单 |
输入框 | 供用户输入值的文本框 |
状态栏项 | 状态栏中的图标、按钮或文本 |
进度 | 在 UI 中显示进度指示器 |
树视图 | 创建类似于用于定义工作区的树(可以放在视图或视图容器中) |
折叠范围 | 自定义代码折叠到装订线上的加号按钮 |
实现 | 实现提供程序(如 TypeScript 等语言可以将声明和实现作为单独的实体) |
差异提供程序 | 源代码管理模式下的差异视图 |
提交模板 | 用于源代码管理模式下的提交 |
除此之外,您还可以调用用户可以在任何菜单中调用的任何功能,以及用户可以传递的任何参数。几乎每个功能都有事件,以及许多文件系统和与文本文件相关的实用程序方法。
开始构建
好了,前言就讲到这里——让我们开始根据我们刚刚学到的知识来构建扩展程序。
创建扩展程序
要构建扩展程序,请从 VS Code 扩展程序生成器 开始。
npm install -g yo generator-code
yo code
接下来,配置选项。以下是我的设置方式

TypeScript 是可选的,但强烈建议使用。这只是另一种提醒您 VS Code 与 TypeScript 非常契合的方式。
现在,您可以在 VS Code 中打开该文件夹。我建议检查初始提交。您可以查看项目中生成的快速入门指南,以了解文件结构。快速尝试将其可视化。转到调试面板,并在调试模式下启动扩展程序。在 extension.ts
中的 activate 方法内放置一个断点,以便实际运行它。该“Hello world”应用程序已注册一个命令,该命令可以在页脚中启动信息消息。使用 ⌘+⇧+P
(Windows 上为 Ctrl+Shift+P
)转到命令菜单,然后选择hello world。

您可以在 registerCommand
回调中放置另一个断点以获取命令事件。
打开 package.json
以了解插件配置的说明。根据您要支持的语言或文件协议类型,将 activationEvents
更改为更具体的事件。All Autocomplete 支持所有文件格式,由 *
表示。如果您想为设置、命令、菜单项、代码片段等做出贡献,还应该查看 contributes
部分。

许多这些贡献在同一个 package.json
文件中包含其他 JSON,其中包含所有信息。某些 API 需要在激活调用中使用的代码,例如用于创建命令的 vscode.commands.registerCommand
。对于自动完成扩展程序,不需要 contributes
部分,可以将其删除。
要在 extension.ts
中使用相同的 All Autocomplete 选项,请将 activate 函数替换为以下内容
export function activate(context: vscode.ExtensionContext) {
context.subscriptions.push(vscode.languages.registerCompletionItemProvider('*', {
provideCompletionItems(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken) {
return [new vscode.CompletionItem("Hello")];
}
}));
}
您可以使用对象中的更多选项指定有关完成项的更多详细信息,例如附加的文档。现在,如果您调试此代码并键入 H
,您应该会在完成菜单中看到 Hello。注册大多数基于语言的提供程序的代码几乎相同。

您可以在vscode.languages
中看到“All Autocomplete”菜单,它提供了注册提供程序的选项。每个提供程序都有一组自己的参数,我们可以像填充完成项提供程序一样填充它们。

document
对象提供对文档的访问,并提供实用程序方法来访问特定位置和范围的文本。强烈建议使用这些API来访问所有文档,而不是使用原始的Node.js API。
您可以根据需要解析文档,或者维护一个数据结构(例如All Autocomplete中使用的Trie),以便在用户键入时优化搜索输入。
提示:如果您正在寻找一些文本选择/操作API,很可能已经有一个可用的API了。无需重新造轮子。您可以使用document.getText(document.getWordRangeAtPosition(position))
精确地获取文本。在任何VS Code对象上Alt+Click
以获取类结构和JSDoc文档。
发布扩展
扩展完成后,就可以将其发布到市场了。VS Code有一个用于发布的命令行工具(vsce
),但它需要创建一个帐户。
以下是准备扩展以供提交的方法
- 清理包:
package.json
和README.md
文件提供了扩展的描述和详细信息,这些信息会在市场中显示。整理这些文件并填写所有缺失的信息非常重要,以便文档清晰易懂。最好在仓库中添加一些徽章和自描述GIF。 - 创建帐户:您需要创建一个Visual Studio Team Services(VSTS)帐户。这是VS Code与Visual Studio唯一关联的地方。您需要注册并获取访问令牌。VSTS界面有点混乱,但您无需学习新的代码管理工具即可发布。转到安全部分获取访问令牌。(不要像我一样犯错,将菜单中的齿轮图标与安全混淆。)
- 安装:使用vsce命令行工具发布扩展。它可以在npm中使用,并且非常易于使用。

提示:VSTS的访问令牌每年都会过期,因此帐户信息非常重要。它还用于回复市场上的评论,尽管大多数用户活跃在GitHub上,并且您更有可能在那里获得错误和功能请求。
npm install -g vsce # One time installation
vsce create-publisher <name> # One time create publisher
vsce login # One time login. Asks for access token.
vsce publish <version> # Publish or update the extension
VS Code不会在服务器上编译扩展。请确保编译扩展创建的输出文件夹是最新的。还要确保检查文件名的大小写,因为错误的文件路径将在Linux中中断。Node中的原生模块非常麻烦,不应使用。不可能为特定Electron版本编译并提供所有平台变体。(有人需要为npm创建一个PhoneGap构建!)随着WebAssembly和N-API的出现,这种情况会随着时间的推移而得到改善。
支持和维护
VS Code团队在GitHub和StackOverflow上非常活跃。GitHub是您可能在API中发现的错误的正确提交位置。该团队反应相当迅速,但您需要像处理任何有帮助的错误报告一样,使上下文极其清晰。
您应该为您的扩展创建一个GitHub仓库,并期望用户直接在GitHub上提交问题。预计VS Code用户精通工具和技术(其中一些人可能比您拥有更多的知识)。即使这是一项免费的工作,保持谦逊并将问题报告者视为客户也是正确的行为。
性能提示
VS Code 性能良好,因为它构建于一个体系结构之上,该体系结构隔离了诸如可能导致速度变慢的扩展之类的事物。如果您的扩展没有及时返回,您的输出可能会被忽略。
以下是一些有助于维护编辑器性能的事项
- 使用官方API:很容易忽略它们并构建自己的API。“类型”文件非常棒,并且包含所有可用API的文档。在那里搜索五分钟可以节省大量时间。如果您需要一些文件,在大多数情况下,最好请求VS Code在编辑器中打开它,而不是从磁盘读取它(除非您正在读取数千个文件并且没有将其保持打开状态)。
- 公开选项:确保有一种方法可以让用户关闭依赖于繁重事件的功能,例如每次按键。在您的机器上可能感觉不到,但这不适合这样做。开发人员会永远保留他们的点文件,如果存在他们需要解决的问题,他们会花时间浏览选项。如果每次按键都不可能,公开一种优雅降级的方法并无害处。
- 子进程:开发人员工具——尤其是在命令行上——非常快且经过良好优化。如果您需要处理大量可能使JavaScript线程窒息的文件,请调用本地工具并礼貌地要求用户安装依赖项。Electron 有局限性,我们应该接受它们。
总结
VS Code 是一款非常灵活的应用程序,它几乎将其所有核心功能都提供给扩展开发人员。开发和调试扩展的工作流程非常简单,每个 JavaScript 开发人员都应该乐于尝试。除了改善我们自己的生活之外,开发扩展的最大优势在于能够看到一个大型 TypeScript 项目的实际应用。仅凭这一点,我建议所有用户都尝试一下,并在评论中分享您的扩展。
我的扩展已在VS Code市场上发布,我也很乐意收到您对此的反馈。🙂