vscode 插件_vscode插件体系详解

vscode 作为一款网红 IDE,其丰富的插件让人叹为观止,通过 vscode 提供的插件机制,我们几乎可以自定义 vscode 的所有细节。事实上很多 vscode 的核心功能也是通过插件实现的。

本文我们将从以下三个方面详述 vscode 的插件机制:

  • 插件的基本结构

  • 插件执行环境

  • 插件的运行流程

阅读本文后续内容,需要对 vscode 的插件开发有基本的了解。关于 vscode 的插件开发可参考 vscode 的官方教程 。

1. 插件基本结构

vscode 的官方教程 中有详细的插件开发文档;并且在 github 上提供了丰富插件案例, 从 UI 定制到代码自动补全都有可借鉴性很高的 demo。本文并不打算详诉插件开发的细节,我们更多的关注 vscode 是如何设计和实现这套插件架构的。

我们首先从一个插件项目的 package.json来了解其基本结构。 package.json中 main 指定了插件的入口函数,而 contributes 和 activationEvents 分别描述的插件的扩展点和触发事件。如下面代码所示:

"main": "./out/extension.js","contributes": {
        "commands": [        {
          "command": "extension.helloWorld",       "title": "Hello World"   }    ]}"activationEvents": [    "onCommand:extension.helloWorld"]

扩展点和触发事件是两个比较重要的概念,我们先简单解释下,后续讲到插件注册时再详细描述。

contributes(扩展点)用于定义插件要扩展 vscode 哪部分功能;vscode 暴露出多个扩展点,包括 commands (命令面板)、configuration (配置模板)等

activationEvents(触发事件)用于定义插件何时执行,当指定的事件发生时插件才会执行

有一类特殊的插件的 activationEvents为通配符 *,这类插件称为 EagerExtensions,它们会在插件环境初始化完成后自动执行,而不需要其他事件触发。

2. 插件执行环境

vscode 的第三方插件的质量往往难以保证,因此需要设计一套隔离机制,将核心功能和第三方插件的执行环境隔离,保证第三方插件挂了,vscode 的核心功能依然可用。由于不想增加理解成本,本文所讲的 vscode 插件机制是指纯 web 版 vscode,和基于 electron 的桌面版 vscode 原理类似。

插件环境初始化入口的在 vs/workbench/services/extensions/browser/extensionService.ts的构造函数中, _initialize函数中的第一步就是初始化插件执行环境。

protected async _initialize(): Promise<void> {
        perf.mark('willLoadExtensions');    this._startExtensionHostProcess(true, []);  //启动插件worker进程,建立rpc通道,注入api    this.whenInstalledExtensionsRegistered().then(() => perf.mark('didLoadExtensions'));    await this._scanAndHandleExtensions();     this._releaseBarrier();}

2.1 环境隔离与通信

(1)worker 进程创建

插件环境初始化的第一步就是创建一个 webworker 用于运行插件逻辑,防止不可信的插件影响到 vscode 核心功能。通过调用 vs/workbench/services/extensions/browser/webWorkerExtensionHostStarter.ts的 start方法创建一个新的webworker作为插件的执行环境。

const url = getWorkerBootstrapUrl(require.toUrl('../worker/extensionHostWorkerMain.js'), 'WorkerExtensionHost');const worker = new Worker(url, { name: 'WorkerExtensionHost' });
(2)主进程与 worker 信道建立

webWorkerExtensionHostStarter.ts的 start方法在创建 webworker 后就封装一个 IMessagePassingProtocol接口返回。如下代码所示:

start(){
       .....   const protocol: IMessagePassingProtocol = {
            onMessage: emitter.event,  send: vsbuf => {
          const data = vsbuf.buffer.buffer.slice(vsbuf.buffer.byteOffset, vsbuf.buffer.byteO
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值