构建我自己的 VS Code 扩展的经验

Avatar of Atishay Jain
Atishay Jain 发表

DigitalOcean 为您旅程的每个阶段提供云产品。立即开始使用 200 美元的免费额度!

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

接下来,配置选项。以下是我的设置方式

VS 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 部分。

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。注册大多数基于语言的提供程序的代码几乎相同。

All Autocomplete 菜单

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

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.jsonREADME.md文件提供了扩展的描述和详细信息,这些信息会在市场中显示。整理这些文件并填写所有缺失的信息非常重要,以便文档清晰易懂。最好在仓库中添加一些徽章和自描述GIF。
  • 创建帐户:您需要创建一个Visual Studio Team Services(VSTS)帐户。这是VS Code与Visual Studio唯一关联的地方。您需要注册并获取访问令牌。VSTS界面有点混乱,但您无需学习新的代码管理工具即可发布。转到安全部分获取访问令牌。(不要像我一样犯错,将菜单中的齿轮图标与安全混淆。)
  • 安装:使用vsce命令行工具发布扩展。它可以在npm中使用,并且非常易于使用。
VSTS中的安全设置

提示: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构建!)随着WebAssemblyN-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市场上发布,我也很乐意收到您对此的反馈。🙂