從小白到大白 — 如何開(kāi)發(fā) VSCode 插件
大廠技術(shù) 高級(jí)前端 Node進(jìn)階
點(diǎn)擊上方 程序員成長(zhǎng)指北,關(guān)注公眾號(hào)
回復(fù)1,加入高級(jí)Node交流群
前言
由于之前的國(guó)際化的項(xiàng)目中總是要統(tǒng)計(jì)老項(xiàng)目中待翻譯的內(nèi)容,然后再交由業(yè)務(wù)進(jìn)行翻譯,如果總是人為統(tǒng)計(jì)不僅相當(dāng)耗費(fèi)精力和時(shí)間,而且還不能保證是否有遺漏,因此想通過(guò)編寫(xiě)一個(gè) i18n-helper 插件來(lái)實(shí)現(xiàn)這個(gè)功能。

然而,大家的需求總是出奇的相似(因?yàn)橐呀?jīng)有很多類似的插件存在了),因此沒(méi)必要重復(fù)造輪子了,但是 如何開(kāi)發(fā) vscode 插件 的過(guò)程可以記錄下來(lái),分享給大家!
希望本文對(duì)你有所幫助!!!

跑通官方插件示例
好了,話不多說(shuō),我們先按著 官方文檔 跑一下它的插件用例吧!
生成插件目錄
安裝腳手架
npm install -g yo generator-code
初始化插件目錄
終端運(yùn)行 yo code,按照提示生成目錄即可。

調(diào)試插件
由于官方文檔缺少一些細(xì)節(jié),很容易導(dǎo)致小白調(diào)試插件失敗,再常見(jiàn)的有如下情況。
找不到 Hello World 命令
進(jìn)入對(duì)應(yīng)項(xiàng)目目錄后,按照官方文檔的指示可通過(guò)如下兩種方式進(jìn)行調(diào)試:
按快捷鍵 F5
點(diǎn)擊編輯器左下方的
Run Extension
接著按下 Ctrl + Shift + P,并輸入 Hello World 命令,發(fā)現(xiàn)無(wú)法找到對(duì)應(yīng)的命令:

這個(gè)原因主要是因?yàn)?vscode 版本不一致造成的:
package.json 文件中指定的 vscode 版本號(hào)

當(dāng)前實(shí)際的 vscode 版本號(hào):

解決方案自然就是保持版本的一致性
升級(jí) vscode 版本
適用于當(dāng)前版本號(hào)低于 package.json 文件中指定的版本號(hào)
【注意】現(xiàn)在 vscode 版本的更新模型已經(jīng)調(diào)整為 “默認(rèn)” 模式,所以現(xiàn)在不會(huì)收到 vscode 需要更新的信息,也無(wú)法進(jìn)行通過(guò) “檢查更新” 按鈕來(lái)進(jìn)行更新
修改 package.json 文件中的 vscode 對(duì)應(yīng)版本號(hào)
這種方式比較簡(jiǎn)單直接,就是修改為和當(dāng)前正在使用的 vscode 版本保持一致即可,如下:

Hello World 命令報(bào)錯(cuò)
經(jīng)過(guò)上述操作后,重新啟動(dòng)調(diào)試,按下 Ctrl + Shift + P,并輸入 Hello World 命令,就可以找到對(duì)應(yīng)的命令了,但是執(zhí)行該命令時(shí)報(bào)錯(cuò)了:

原因就在于我們沒(méi)有編譯文件,此時(shí)注意查看 package.json 文件中的 main 字段會(huì)發(fā)現(xiàn):

很明顯,我們沒(méi)有編譯源文件生成目標(biāo)文件,此時(shí)我們只需要通過(guò) npm run watch 啟用監(jiān)聽(tīng)模式,讓其進(jìn)行編譯即可:

此時(shí)在執(zhí)行命令,就會(huì)發(fā)現(xiàn)成功了:

【實(shí)戰(zhàn)】編寫(xiě) VSCode 插件
插件的三個(gè)概念
激活事件(針對(duì) V1.74.0 之前的 VSCode 版本)
即插件激活的時(shí)機(jī),目的是支持用戶在輸入
Hello World命令后能夠激活插件例如,使用
onCommand進(jìn)行注冊(cè)onCommand:extension.helloWorld
-
發(fā)布內(nèi)容配置
VS Code 通過(guò)
package.json進(jìn)行擴(kuò)展,通過(guò)配置 插件清單字段 便于開(kāi)發(fā)插件例如,使用
contributes.commands綁定一個(gè) 命令 IDextension.helloWorld,目的是讓Hello World命令就可以在命令面板中匹配到等-
VS Code API
插件代碼中需要調(diào)用的一系列 JavaScript API 使用 VS Code 的一些功能特性
例如,通過(guò)
vscode.commands.registerCommand將一個(gè)函數(shù)綁定到對(duì)應(yīng)的 命令 IDextension.helloWorld上,激活命令時(shí)執(zhí)行的就是該函數(shù)等
在 VSCode 中預(yù)覽 SVG 文件 — <img /> 標(biāo)簽預(yù)覽
當(dāng)然相關(guān)的 svg 插件已經(jīng)有不少了,這里只是用這個(gè)簡(jiǎn)單的需求來(lái)舉個(gè)例子,方便讓大家更容易理解。
SVG 文件在 VSCode 中的原始展示效果

發(fā)布內(nèi)容配置 — package.json 文件
面向用戶的命令
首先,我們要注冊(cè)命令,讓用戶能夠使用我們的插件,這里我們就簡(jiǎn)單支持如下兩種方式:
Ctrl + Shift + P 匹配命令
只需要在 package.json 中的
contributes.commands進(jìn)行如下配置即可,詳情可見(jiàn) contributes.commands"contributes": {"commands": [{"command": "svg-viewer.previewsvg","title": "Preview SVG"}]}鼠標(biāo)右鍵菜單選擇命令
這種方式相對(duì)于上面的方式來(lái)講更簡(jiǎn)便,只需要在 package.json 中的
contributes.menus進(jìn)行如下配置即可,詳情可見(jiàn) contributes.menus"contributes": {"menus": {"editor/context": [{"command": "svg-viewer.previewsvg"}]}
上述 鼠標(biāo)右鍵菜單選擇命令 的配置有一點(diǎn)不好,那就是安裝此插件后,在任何文件中右鍵都會(huì)顯示 Preview SVG 選項(xiàng),此時(shí) 調(diào)試效果如下:


因?yàn)槲覀兊谋疽馐穷A(yù)覽 SVG 文件,而不是其他文件,因此對(duì)于不符合的文件就沒(méi)有必要展示此選項(xiàng)了,此時(shí)可以通過(guò) when 子句上下文 來(lái)控制顯示隱藏命令選項(xiàng),此時(shí)配置更改為:
"contributes": {"menus": {"editor/context": [{"command": "svg-viewer.previewsvg","when": "resourceExtname == '.svg'"}]}
調(diào)試效果如下:


使用 VSCode API
注冊(cè)命令
上述我們配置好了命令,現(xiàn)在就需要注冊(cè)命令了,也就是決定當(dāng)命令激活時(shí)需要做些什么事情,即只需要在 extension.ts 文件的 activate 方法中做如下修改即可:
// 執(zhí)行命令時(shí)被激活export function activate(context: vscode.ExtensionContext) {// 使用控制臺(tái)輸出診斷信息(console.log)和錯(cuò)誤(console.error)// 這行代碼只會(huì)在你的擴(kuò)展被激活時(shí)執(zhí)行一次console.log('Congratulations, your extension "svg-viewer" is now active!');// 注冊(cè)命令,commandId 參數(shù)必須與 package.json 中的 command 字段匹配let disposable = vscode.commands.registerCommand("svg-viewer.previewsvg",() => {// 具體要做的內(nèi)容});context.subscriptions.push(disposable);}
使用 Webview
平時(shí)我們通過(guò)瀏覽器使用 <img> 標(biāo)簽可以查看 svg 文件的效果,例如:

那么在 VSCode 中可不可以也以這樣的方式來(lái)實(shí)現(xiàn)呢?
那當(dāng)然是可以的。
我們可以使用如下代碼編輯器中創(chuàng)建一個(gè) Webview ,然后其中的 html 選項(xiàng)內(nèi)容就可以用我們常見(jiàn)的 html 結(jié)構(gòu) 來(lái)填充,并作為最終結(jié)果來(lái)進(jìn)行 渲染,例如:
// 創(chuàng)建并顯示新的 webviewconst panel = vscode.window.createWebviewPanel("SVGPreview", // 只供內(nèi)部使用,即 webview 的標(biāo)識(shí)"SVG Preview", // 面板標(biāo)題vscode.ViewColumn.One, // 給新的 webview 面板一個(gè)編輯器視圖{} // Webview 選項(xiàng));// 設(shè)置HTML內(nèi)容panel.webview.html = `<html lang="en"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>SVG Preview</title></head><body><img src="${目標(biāo)文件地址}" /></body></html>`;
獲取目標(biāo)文件的 base64 格式
由于我們打開(kāi)相應(yīng) svg 文件后右鍵進(jìn)行預(yù)覽,那么第一步就得先獲取當(dāng)前這個(gè)文件的路徑,這就又得需要使用的 VSCode API 了,如下
const editor = vscode.window.activeTextEditor;let url = editor.document.fileName; // 獲取到的就是對(duì)應(yīng)文件的絕對(duì)路徑

但是如果你直接把這個(gè)路徑作為 <img> 標(biāo)簽的 src 屬性是沒(méi)法沒(méi)正常渲染的,大致如下:

既然如此,那么我們可以把這個(gè) svg 文件讀取到,然后把它轉(zhuǎn)成 base64 的格式,再交由 <img> 標(biāo)簽使用即可,此時(shí)我們就需要使用到 node 內(nèi)置的 fs 模塊了,即:
const fs = require("fs");const content = fs.readFileSync(url);return `data:image/svg+xml;base64,${content.toString("base64")}`;
源代碼 & 效果展示
需要查看源碼的可點(diǎn)此獲取:源代碼
經(jīng)過(guò)上述的處理我們就可以在 VSCode 中預(yù)覽 svg 文件了,效果如下:

在 VSCode 中預(yù)覽 SVG 文件 — <svg> 標(biāo)簽預(yù)覽
上述方案雖然可以實(shí)現(xiàn)我們需要的功能,但是對(duì)于 svg 文件來(lái)講還是復(fù)雜了,因?yàn)樵跒g覽其中是可以直接渲染 <svg> 標(biāo)簽的,而 svg 文件的內(nèi)容不就是 <svg> 標(biāo)簽嗎,那么我們只需要把文件內(nèi)容讀取出來(lái),直接填充到 webview.html 中就好了,根本不需要轉(zhuǎn)成 base64 格式。

這個(gè)方案比較簡(jiǎn)單,這里直接貼出 extension.ts 文件中的代碼了:
import * as vscode from "vscode";// 執(zhí)行命令時(shí)被激活export function activate(context: vscode.ExtensionContext) {const fs = require("fs");// 注冊(cè)命令,commandId 參數(shù)必須與 package.json 中的 command 字段匹配let disposable = vscode.commands.registerCommand("svg-viewer.previewsvg",() => {const url = getActiveTextUrl();const content = fs.readFileSync(url, "utf-8");opedWebview(content);});context.subscriptions.push(disposable);}// 獲取當(dāng)前文件路徑export function getActiveTextUrl(): string {let url = "";const editor = vscode.window.activeTextEditor;if (editor) {url = editor.document.fileName;}return url;}// 創(chuàng)建并顯示新的 webviewexport function opedWebview(content: string) {const panel = vscode.window.createWebviewPanel("SVGPreview", // 只供內(nèi)部使用,即 webview 的標(biāo)識(shí)"SVG Preview", // 面板標(biāo)題vscode.ViewColumn.One, // 給新的 webview 面板一個(gè)編輯器視圖{} // Webview 選項(xiàng));// 設(shè)置HTML內(nèi)容panel.webview.html = getWebviewContent(content);}// 渲染模版export function getWebviewContent(content: string) {return `<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>SVG Preview</title><style>html,body {width: 100%;height: 100%;}body {display: flex;justify-content: center;align-items: center;}svg {max-height: 90%;}</style></head><body>${content}</body></html>`;}// 停用命令時(shí)執(zhí)行export function deactivate() {}
發(fā)布
發(fā)布到官網(wǎng)應(yīng)用市場(chǎng)
通過(guò) 這個(gè)地址 注冊(cè)開(kāi)發(fā)者賬號(hào),然后按提示發(fā)布到官網(wǎng)應(yīng)用市場(chǎng)即可。

使用 vsce 打成 vsix 插件
這種方式可以實(shí)現(xiàn)即使 沒(méi)有發(fā)布到應(yīng)用市場(chǎng),也可以直接通過(guò)對(duì)應(yīng)文件的方式進(jìn)行插件的安裝和使用。
安裝 vsce 工具
安裝命令 npm i vsce -g
打包生成 .vsix 文件
直接使用 vsce package 命令進(jìn)行打包,完成后就會(huì)生成一個(gè) .vsix 文件,這個(gè)也就是在后續(xù)安裝插件時(shí)要使用的文件。
【
注意】 在使用這個(gè)命令打包時(shí),可能會(huì)出現(xiàn) vsce 所需要支持的 VSCode 最低版本和當(dāng)前使用版本之間存在出入,導(dǎo)致打包失敗:
特別是如果按照前文的方式直接修改
package.json文件中的版本號(hào)時(shí),此時(shí)最好還是將 VSCode 版本進(jìn)行升級(jí),而不是手動(dòng)修改版本號(hào)。
安裝 vsix 插件
按照如下方式操作并選擇對(duì)應(yīng)的 .vsix 文件即可.

最后
歡迎關(guān)注同名公眾號(hào)《
程序員成長(zhǎng)指北》,本公眾號(hào)會(huì)定期分享技術(shù)干貨,也可快速加入前端交流群!
以上就是本文的全部?jī)?nèi)容了,文中沒(méi)有過(guò)多介紹那些沒(méi)有用到的內(nèi)容(如 package.json 相關(guān)配置),因?yàn)閮?nèi)容太多了,所以大家多查閱下官方文檔即可。

通過(guò)本篇文章,希望能讓你從一個(gè) VSCode 插件開(kāi)發(fā) 的小白變成大白,能夠?yàn)閳F(tuán)隊(duì)賦能,或者作為自己的一個(gè)技能亮點(diǎn)。
希望本文對(duì)你有所幫助!!!
Node 社群
我組建了一個(gè)氛圍特別好的 Node.js 社群,里面有很多 Node.js小伙伴,如果你對(duì)Node.js學(xué)習(xí)感興趣的話(后續(xù)有計(jì)劃也可以),我們可以一起進(jìn)行Node.js相關(guān)的交流、學(xué)習(xí)、共建。下方加 考拉 好友回復(fù)「Node」即可。
“分享、點(diǎn)贊、在看” 支持一下

