vscode 是时下最流行的开发工具之一,高逼格的 UI 和各种酷酷的插件,不仅提高了使用者的开发效率,还让他们的形象大为改善,不再是人们眼中的“死肥宅”。使用 vscode 很潮,但更潮的就是为它开发插件。作为今年的兴趣点,我也投身于 vscode 插件开发者大军之中。
vscode 的插件开发并不需要太高深的技术,就是普通的开发技术的组合。因为面向的用户就是开发者,所以一般情况下主要是对开发者工作现场(如编辑文本框)的增强,并搭配完成任务的各种命令,很少需要复杂的 UI 。但凡事总有例外,当需要 GUI 加持的时候,就轮到 Webview 出场了。
Webview 开发本身也很简单,就两个任务:
可是,就算是简单的任务,做多了你也会发现还是存在一些值得优化的空间,避免在每个新页面开发都重复以下的事情:
这样做有助于设定一个简单的开发模型,处理好消息、处理和展示三者的关系,不必每次开发新页面时“copy - paste - change”,而是采用一致的模型并促进组内协作。
于是,vscode-page 应运而生。
简单地讲,vscode-page 是一个针对 vscode Webview 开发的轻量级页面微框架,抽象了 html 与 WebviewPanel 之间的通信交互,使得开发者只需要关心具体业务逻辑。其整个架构图如下:
看到这张图,熟悉 Web 开发框架的同学应该已经秒懂整个设计:
更详细的说明请参见 README 。
这里没有采用花哨的 Angular 、React 和 Vue ,主要就是为了简单和轻量。并且,在 vscode Webview 这种受限的环境下,使用传统的 jQuery + BootStrap + Handlebars 就是最佳选择,而且一般情况下插件的 GUI 也不会太复杂,前面的几个工具已经足以应对。
vscode-page 的使用很简单:
在这里定义消息请求和响应内容,其中:
这里有几点注意,在每个页面前面添加以下两行:
<base href="{{base}}" />
<script type="text/javascript">
"{{init}}"
</script>
一般情况下,你直接调用:initEventListener() 来完成初始化就行了,它实现了:
假如你想处理,则可以换一种初始化方式,传入处理函数:
initEventListener(message => {...});
此时,你可以从 message.result 拿到结果。
这个过程没有什么复杂的,就是定义三个属性:
详细例子,参见:https://github.com/DTeam-Top/vscode-page/blob/master/example/src/home.ts 。
值得一提的是,MessageMapping 还支持 forward 模式,即请求处理之后,直接转到另一个 command ,以它的处理结果为最终处理结果,类似 Web 开发中的 forward 模式。
{
command: "submitRepositories",
handler: async parameters => {
……
},
forward: "ready"
},
上面的 ready 就是另一个 MessageMapping 定义的 command 名。
这个最简单,就一句话:
createOrShowPage(
'name',
'ext.home',
'Sample Page',
'pages',
'home.html',
context,
messageMappings
);
定义了 title、根目录和需要加载的页面。
关于使用的完整例子请结合 README 和样例工程来看,后者是我们即将试水发布的一个 vscode 插件,用于帮助开发者或企业搭建自己的私有插件仓库。因为总有些时候会需要私有插件仓库,:)
虽然插件开发指南已经很详尽,但初学者总是会遗漏一些细节,在开发时才发现文档中早有提及。这里尤其值得一提的就是 Webview 的资源加载问题,因为它浪费了我一些时间。
最简单的方案,当然就是直接使用 vscode-page 插件就行了,它已经替你 cover 了一些细节,你只需照常使用就行,你可以查看这个页面。
假如不使用 vscode-page ,我也没打算藏着掖着,只需要复制下面的几行代码即可:
const rootString = path.join(context.extensionPath, base);
const localResourceRoots = vscode.Uri.file(path.join(rootString, '/')).with(
{
scheme: 'vscode-resource',
}
);
panel = vscode.window.createWebviewPanel(
viewType,
title,
vscode.ViewColumn.One,
{
enableScripts: true,
retainContextWhenHidden: true,
localResourceRoots: [localResourceRoots],
}
);
const pagePath = path.join(rootString, page);
panel.webview.html = fs
.readFileSync(pagePath, 'utf-8')
.replace('{{base}}', localResourceRoots.toString());
当然,你得记得在页面中在添加一行:
<base href="{{base}}" />
从代码中我相信你已经看出来一些端倪:scheme: ‘vscode-resource’,它并非一般 Web 开发中的 file: 。同时也要记得设置 localResourceRoots 属性。在开发 vscode-page 时发现使用 vscode-page 的插件总是没法加载自己的资源,报:ERR_ACCESS_DENIED ,后来发现是因为没有设置这个属性。
开发 Webview 肯定需要类似 Web Dev Tools 那样的浏览器查看工具,vscode 也有。输入:Open Webview Developer Tools 就能激活。
因为本质上 vscode 插件开发是前端工程的范畴,并且我们团队主要采用 TypeScript ,因此用到的插件和规范如下:
代码风格:
风格可商量余地:
相关插件:
作为插件发布的前奏,vscode-page 已经发布(0.0.1),工程路径:https://github.com/DTeam-Top/vscode-page ,欢迎加星或使用,😄。
觉得有帮助的话,不妨考虑购买付费文章来支持我们 🙂 :
付费文章