简单谈下大家都熟知的 VS Code,它是微软推出的轻量级编辑器,本身是基于当下热门的同样由微软开发的 TypeScript,同时又基于 Electron 开发。尤其对 TypeScript、JavaScript 还有 Node.js 开发提供了强大的支持。内部集成了包管理器、终端、Git 版本管理、代码 diff 等功能。
实际上能让 VS Code 称得上是一个万能的 IDE 正是由于它庞大的扩展生态。对于我们前端开发者来说,只要了解相关 API,VS Code 扩展的开发基本没有门槛。
VS Code has a very rich extensibility model and there are many ways to extend the tool. However, we do not provide direct access to the underlying UI DOM to extension writers. With VS Code, we’re continually trying to optimize use of the underlying web technologies to deliver an always available, highly responsive editor and we will continue to tune our use of the DOM as these technologies and our product evolve.
VS Code 提供了丰富度扩展能力模型,但是不允许直接访问底层 UI DOM,也就是说很难通过插件去改变 IDE 外观,这是因为 UI DOM 这一层可能会随着 VS Code 优化频繁改动,为了防止这部分优化受限于插件依赖,干脆就把 UI 定制能力限制起来。除此之外,配合 VS Code 我们提供的 API,我们可以实现各种各样强大的功能:主题/图标定制、智能提示、自动补全、悬停提示、语法高亮、引用跳转等等,甚至可以 DIY WebView…
虽然不允许直接访问 DOM,但是提供了内置的 UI 组件比如智能提示框。出于性能、兼容以及 IDE 本身的稳定性来考虑,插件在独立进程 extension host process
中运行。所以即便是插件崩溃了也不会影响 VS Code 的正常运行,并且插件隔离不会影响 VS Code 的启动时间。
VS Code 为我们开发插件提供了方便的脚手架
除了 Git 和 Node.js 以外,还需要要安装 Yeoman 和 VS Code Extension Generator 两个工具
npm install -g yo generator-code
如果插件项目比较大的话,更推荐使用 TypeScript 来进行开发,也是微软推荐的开发方式
输入 yo code
命令输入配置来生成项目模板
配置项包括插件名称、描述、关键词等等,以及是否创建 Git 仓库,选择包管理器等
确认后脚手架会帮我创建完整的开发目录
内部还包含了一个 Hello World 的小 demo
├── .vscode // 扩展配置
│ ├── launch.json
│ ├── settings.json
│ └── tasks.json
├── .vscodeignore // 发布忽略配置
├── .gitignore // Git忽略配置
├── README.md
├── src // 主入口文件
│ └── extension.ts/js
├── test
│ ├── extension.test.ts/js
│ └── index.ts/js
├── node_modules
│ ├── vscode
│ └── typescript
├── out // ts编译后输出目录
│ ├── src
│ | ├── extension.js
│ | └── extension.js.map
│ └── test
│ ├── extension.test.js
│ ├── extension.test.js.map
│ ├── index.js
│ └── index.js.map
├── package.json // 清单文件
├── tsconfig.json // ts配置文件
├── typings // ts类型定义目录
│ ├── node.d.ts
│ └── vscode-typings.d.ts
└── vsc-extension-quickstart.md
其中我们主要关注两个核心文件
入口文件 extension.js/ts
与配置文件 package.json
package.json 作为清单文件用来描述插件的 meta 信息
不仅描述了插件的信息,还描述了插件的功能
VS Code 还增加了一些特有字段
如用来配置插件加载时机的 activationEvents
和扩展贡献点 contributes
VS Code 会在启动时读取所有插件的 package.json 并对描述功能的 contributes
做特殊处理
{
"name": "demo", // 插件名称
"displayName": "demo", // 发布名称
"description": "", // 插件描述
"version": "0.0.1", // 插件版本
"engines": { // 版本限制
"vscode": "^1.32.0"
},
"categories": [ // 所属类别
"Other"
],
"keywords": [ // 关键词
"demo"
],
"publisher": "congpeisen", // 发布者姓名
"activationEvents": [ // 加载/激活方式
"onCommand:extension.sayHello"
],
"main": "./out/extension", // 插件入口
"contributes": { // 扩展贡献关联点
"commands": [{
"command": "extension.sayHello",
"title": "Hello World"
}]
},
...
}
详细的扩展清单见 Extension Manifest
VS Code 在生成的清单文件中的 activationEvents 下声明了该插件的懒加载激活方式为 onCommand
所触发命令为 extension
命名空间下的 sayHello
这样当执行该命令执行后后插件会被激活
同时在 contributes 下注册了一个 extension.sayHello
的命令
用户便可以在命令面板中输入 Hello World
来触发 extension.sayHello
命令
activationEvents 中目前插件有以下九种激活方式:
onLanguage:${language}
打开特定语言文档时触发onCommand:${command}
在命令面板中执行特殊命令时触发onDebug
启动调试时触发workspaceContains:${filename}
工作区包含特定文件时触发onFileSystem:${scheme}
特殊文件或文件夹被读取时激活onView:${viewId}
特定 view 被展开时激活onUri
打开 Uri 时激活onWebviewPanel:${viewType}
特定 webview 被打开时激活*
随 VS Code 启动激活(不推荐使用)事件激活详见 activation-events
contributes 中可注册的功能点如下:
configuration
插件配置 - 用户在 setting.json 中设置configurationDefaults
插件默认配置commands
命令 - 用户在 Command Palette 输入激活menus
菜单栏 - 点击菜单栏执行所关联命令keybindings
快捷键 - 使用快捷键执行所关联命令languages
语言 - 扩展新类型语言或关联特定语言类型debuggers
调试器 - 通过 debug 协议进行通信breakpoints
断点 - 声明 debugger 支持的语言类型grammars
语法 - 关联语法描述文件实现语法高亮themes
主题 - 关联主题配置文件实现主题定制snippets
代码片段 - 关联代码片段文件实现代码补全jsonValidation
json 格式校验views
文件查看器及调试视图定义viewsContainers
视图容器定义problemMatchers
错误匹配定义problemPatterns
匹配模式定义taskDefinitions
贡献任务定义colors
新主题颜色定义typescriptServerPlugins
TypeScript 服务器插件功能贡献点使用详见 contribution-points
'use strict';
import * as vscode from 'vscode';
export function activate(context: vscode.ExtensionContext) {
let disposable = vscode.commands.registerCommand('extension.sayHello', () => {
vscode.window.showInformationMessage('Hello World!');
});
context.subscriptions.push(disposable);
}
export function deactivate() {
}
在主入口文件中定义了触发 extension.sayHello 所要执行的逻辑 ———— 弹出 Hello World 信息
与 package.json 不同,除了配置 *
以外,插件源码是不会随 VS Code 启动而加载的
extension 中导出了两个函数:
activate
插件被激活时执行,触发条件在 package.json 下的 activationEvents 中定义,用做插件功能初始化deactivate
IDE 关闭时触发,用做清理工作extension 入口文件中引入的 VS Code 包含了 IDE 为我们开发扩展提供的所有 API
命名空间组织如下:
commands
命令注册等相关 APIdebug
调试相关 APIenv
环境相关信息extensions
跨插件 API 调用languages
语言相关 APIscm
源码管理控制台相关 APItasks
任务相关 APIwindow
编辑器窗口相关 APIworkspace
工作区相关 API详见 vscode-api
开发时调试可以使用 fn+F5(Win: F5)可以进入独立的调试窗口
或在左侧活动栏中手动点击调试
若运行无误的话,使用 ⇧+⌘+P 或 fn+F1(Win: Ctrl+Shift+P / F1)快捷键进入命令面板
输入 Hello World 就可以看到弹出的提示框
若选择 TypeScript 来进行开发,启动调试后,根据 .vscode/task.json 下的定义
TypeScript 编译器会先对 ts 源码编译为 js 放在 out/. 目录下
相当于执行了 npm run compile
通过调试状态下的调试栏同样可以进行断点调试
在插件开发时的 console.log 打印数据会显示在底部的调试控制台
在开发过程中出现的语法或类型等错误,IDE 会在底部问题栏中报出 error 信息
利用 VS Code 内置的插件还可以让我们在开发时使用 cmd+鼠标左键 跳转到 vscode.d.ts 中的对应类型声明
使用自己开发的插件有三种办法
如果只是自己使用的话,把所开发插件直接放到 VS Code 的插件目录下即可
各系统目录位置:
%USERPROFILE%\.vscode\extensions
$HOME/.vscode/extensions
$HOME/.vscode/extensions
但是开发插件仅自己使用的情况比较少
更常见的做法是打包成 vsix 文件或将插件发布到插件市场
不管是打包还是发布都需要安装一个发布工具 vsce
同时都需要关联远端 Git 仓库(package.json / repository)
npm install -g vsce
如果所开发插件涉及不便对外的信息时,可以选择将插件打包为一个 vsix 文件
vsce package
输入该命令后,目录下会输出一个 *.vsix
的 VS 扩展包文件
安装插件时需要在插件栏右上的查看更多选项中 Install from VSCE
进行安装
发布到扩展市场相比直接打包稍微麻烦一些
大体流程如下:
同样使用 vsce 提供的命令来创建发布者
vsce create-publisher [publisher-name]
若已有发布账号可直接登录
vsce login [publisher-name]
最后使用 vsce publish
来进行插件发布
它会根据插件的 package.json 中版本号进行发布
除此之外还可以使用以下命令来进行增量发布
vsce publish major
vsce publish minor
vsce publish patch
分别是针对主版本号、次版本号和修订版本号的自增发布
这些命令会自动对 package.json 进行修改
e.g. patch 发布: 0.0.1 -> 0.0.2
其他命令可通过 vsce -h
自行查阅
当发布成功无 error 信息时,大概几分钟就可以在插件市场搜索到新版本插件的发布
主页传送门