写点什么

如何做一款属于自己的 VS Code 插件?

作者:梁龙先森
  • 2021 年 12 月 12 日
  • 本文字数:3250 字

    阅读完需:约 11 分钟

如何做一款属于自己的VS Code插件?

VS Code 编辑器晋升为前端人必备开发利器,很大一部分是源于它强大的插件系统。比如,用于 JS 语言纠错的 Eslint 插件、用于美化 JS/TS/CSS 的 Pretiter 插件、或者用于映射 vscode 上的断点到 chrome 上方便调试的 Debugger for Chrome 插件等等,它们组成了一个庞大的生态系统,对前端的日常开发在工程质量、研发效率提升上,无疑提供了强有力的支撑。那前端人如果能够自行开发一款对团队研发效率或工程质量有提升的插件,这比一直沉浸于业务代码存在另一份成就感。下面开始进入了解 VS Code 架构设计和实践。

一、VS Code 架构设计

首先,VS Code 它的定位是做一款高性能的轻量级的编辑器,所以它们很注重核心功能的性能,对于性能消耗大、资源消耗大的一些特性功能,则交由其他进程来处理。那么对于设计的插件系统,要保证核心功能的性能,那只能让它运行在独立的插件进程。并且进程之间相互隔离,同时又能通过 IPC 进行通信,因此这也保证了主进程的安全稳定。

其次,VS Code 还内置了对 TypeScriptNode.js的 支持。书写 TypeScript 能获得智能提示,并且无需任何配置即可调试 Node.js 代码。当然对于其他语言,它同时提供了统一的 API Language Server Protocol 和 Code Debugging Protocol,每种语言能够通过它获取到类似 IDE 对开发和调试体验。

最后,VS Code 为了保持稳定的交互和视觉设计,对视图这块暴露的能力是非常有限的,并且插件无法访问 DOM 以及操作 UI,以及它提供的 UI 插槽(component slot)也非常少,要绘制 UI 只能通过官方提供的一些内置组件。下面是 VS Code 支持自定义的区域展示:标题栏|活动栏|侧边栏|控制板|编辑组|状态栏。

了解完 VS Code 整体架构,下面完成一个 Hello World 插件应用。

二、环境搭建

在开始开发 VS Code 前,先确保安装了 Node.jsGit

1. 安装命令行工具

npm install -g yo generator-code
复制代码

yo,是 yeoman 的简写,它是一个通用型脚手架。而 generator-code,是基于 yeoman 的规则创建的 vscode 插件模板代码。

2. 初始化项目

执行下面命名,进行项目模板的选配,支持 js/ts 语言、是否初始化 git、是否选用 webpack 等能力初始化。

yo code
复制代码


3. 开启扩展主机窗口

在编辑器中打开项目,并执行F5。此时将打开一个扩展程序主机窗口用于编译和运行扩展程序。


这里要注意的是:需要先查看下 package.json 配置文件,看下属性 "main": "./out/extension.js", 对应的目标文件是否存在,不存在需要先执行下 npm compile 进行编译出该文件,否则扩展执行会找不到入口文件。

4. 执行命令行

初始化项目后,我们在 package.json 配置文件中,可以看到已经注册了命名,如下:



文件中描述的是:注册了一个 Hello World 的指令,插件激活的时机是在执行了:Hello World 命令。那怎么执行呢?在新窗口的命令面板 ( ⇧⌘P ) 中运行 Hello World 命令,则在扩展主机窗口看到对应的交互效果。

5. 应用生命周期

启动了 Hello World 应用,那它是怎么执行的呢?项目的入口执行文件是:src/extension.ts 文件,那么看看这里都做了什么。

// vscode包,包含所有vscode提供的api扩展能力import * as vscode from 'vscode';
// 应用激活时执行的方法export function activate(context: vscode.ExtensionContext) { // 注册命令:hello-world.helloWorld,这个命令得先在package.json先进行定义 let disposable = vscode.commands.registerCommand('hello-world.helloWorld', () => { // 命名执行后的回调函数 vscode.window.showInformationMessage('Hello World from Hello World!'); }); // 上下文订阅命名 context.subscriptions.push(disposable);}
// 应用卸载时执行的方法export function deactivate() {}
复制代码

三、插件实践

1. 定义命令

用于执行的命名都需要在 package.json 进行定义。定义如下:

contributes.commands:定义的命令列表

command:命定的 id

title:命令语句

{  "contributes": {    "commands": [{      "command": "PUPU.generator",      "title": "PUPU"    }]  }}
复制代码

2. 激活时机

我们的插件并不是任何时候都需要它运行,或者只需要它在特定的情况下才运行,这么做是出于性能的考虑。当好 package.jsonactivationEvents 支持配置。

{  "activationEvents": [    // 当执行命名时激活    "onCommand:PuPu.hello",    // 当处于js文件时激活    "onLanguage:javascript",    "onDebug",    // 启动就激活,一般不建议    "*",    // 编辑器启动之后执行,不会影响编辑器启动    "onStartupFinished"  ]}
复制代码

3. 工作区

首先我们了解下工作区的概念。工作区 workspace 是在 VS Code 窗口中打开到一个或多个文件夹的集合。大多数情况下,我们打开一个文件夹作为工作区,但有时候也可以进行高级配置,让一个工作区包含多个文件夹。工作区的设计,让 VS Code 能够做下面这些事:

  • 配置仅适用于一个或多个特定文件夹,而不适用其他文件夹

  • 保留仅在该工作区上下文中有效的任务和调试器启动配置

  • 存储和恢复与该动作区有关联的 UI 状态

  • 仅针对该工作区有选择地启动或禁用扩展

同时,工作区提供了对文件系统监听和文件查找的能力,并且两者都运行在编辑器进程之外,因此应该优先使用它们,而不是用 node 的等效能力替换。

4. 配置监听

安装完插件后,如果该插件支持自定义配置,我们往往在项目中的 .vscode/settings.json 文件进行配置,配置完成保存后,插件就自动刷新了。 workspace 工作区提供了这个能力。

import vscode from 'vscode'
vscode.workspace.onDidChangeConfiguration(() => { // 监听到配置文件变更,则执行该回调函数})
复制代码

5. 文件能力

文件系统接口公开了编辑器的内置能力。它允许扩展处理来自本地磁盘的文件以及来自远程位置的文件,如远程扩展主机或 ftp-servers。

import { workspace } from 'vscode'// 文件复制workspace.fs.copy// 创建文件夹workspace.fs.createDirectory// 删除文件workspace.fs.delete// 读取文件夹workspace.fs.readDirectory// 读取文件workspace.fs.readFile// 修改文件名workspace.fs.rename// 获取文件元信息workspace.fs.stat// 写文件workspace.fs.writeFile// 检查给定的文件系统是否支持写入文件workspace.fs.isWritableFileSystem
复制代码

6. 页面交互

插件提供的页面定制能力是不强大的,下面大体罗列下它在消息提示、选择、用户输入等相关的 UI 能力。

import { window } from 'vscode'// 消息提示window.showErrorMessagewindow.showWarningMessagewindow.showInformationMessage
// 用户输入window.showInputBoxwindow.showOpenDialog// 用户选择window.showWorkspaceFolderPickwindow.showQuickPick// 进度条window.withProgress
复制代码

7. 代码片段

插件支持自定义自己的模板代码,然后在项目中根据输入字符会自动匹配出代码片段。

  1. package.json 定义片段

{  "contributes": {    "snippets": [      {        "language": "javascript",         // 定义模板代码的地方        "path": "./snippets/pupu.json"      }    ]  }}
复制代码
  1. 配置片段

// snippets/pupu.json文件{  "文件头部描述": {    "prefix": "pt",    "body": [      "我是模板生成的代码片段啊"    ],    "description": "我是代码片段"  }}
复制代码

此时当你在文件中输入 pt 关键字,那么会自动联想出 "我是模板生成的代码片段啊" 片段供你选择。

8. 发布打包

vsce 是一款用于打包、发布和管理 VS Code 插件代码的命令行工具。使用它执行:

npm i vsce -g
复制代码

如果我们打包的插件不发布到扩展市场,仅仅在内部使用或者挂载到自己的网站进行执行,那么只需要执行下面命令,那么它会打出以 vsix 为后缀的文件。使用它的时候,再从 vscode 编辑器导入即可。

 
复制代码

那么如果你需要发布到 vscode 插件市场进行账号注册和配置,它的地址是https://marketplace.visualstudio.com/manage

四、总结

到这里我们已经大体描述了如何开发一个 vscode 插件,以及它核心能力的描述。当然还有很多没有描述,比如虚拟文档能力、tree view 等,那么下一片实践一个 GraphQL 代码生成器,直接上手插件开发。

用户头像

梁龙先森

关注

无情的写作机器 2018.03.17 加入

vite原理/微前端/性能监控方案...,正在来的路上...

评论

发布
暂无评论
如何做一款属于自己的VS Code插件?