🦊【前端插件】来开发属于你自己的第一个vscode插件吧🦄

2,555 阅读3分钟

最近我们的技术项目需要做一个vscode extension,功能非常典型,增加snippets,并且鼠标滑动到相应的属性上悬浮出一个链接,方便跳转查看信息,最后将这个extension发布到了vscode Marketplace,这里记录一下是怎么做的~

创建Extension

首先,我们先用脚手架生成一个extension项目,遵从vscode官方来进行创建

image.png 这里有一些选项供大家选择,整体还是很简单的

image.png

使用yo创建的插件项目自带一个command命令,打开项目install依赖后,我们按下F5走插件的调试任务,其实跑的是.vscode中的launch.json,这里可以这一个job跑了preLaunchTask,输出在outFiles里

image.png

在tasks.json中能看到有watch这个task,kind是build并且有isDefault,所以在调试时,会跑起watch来输出dist代码供给新窗口的vscode

image.png

增加Snippets

snippets是便利的代码段,比如我们可以打clg轻松得就出一个console.log

vnx6m-dsafb.gif

我们假设这里要实现一个输入weather输出一个weather组件,并且鼠标悬浮到组件上出一个链接,让用户可以看到更详尽的天气信息

首先我们在根目录下创建一个snippets的文件夹,在其中增加一个weather.json,在package.json中增加对应的snippet路径

// snippets/weather.json
{
  "weather snippets": {
      // 匹配输入的关键字
      "prefix": "weather",
      // 具体生成什么代码
      "body": [
          "<weather",
	  "country='$0'",
	  "city='$1'",
      ],
      "description": ""
  }
}

// package.json
{
  "contributes": {
      "snippets": [
      {
          "language": "javascript",
          "path": "./snippets/weather.json"
      }
      ]
    }
}

现在调试extension,你就可以看到你新生成的snippet了!

碎碎念:

  1. snippets中无法对输入的关键字也就是prefix做正则match,如果你有超多种,只能使用数组列举
  2. snippets中没有提供变量来告诉开发者,用户实际选择了哪一个对应的snippet,对应第一个问题。比如我的prefix为["good_weather", "bad_weather"],我无法知道用户实际选择了哪一个snippet,这样就导致我在实际需求中无法生成对应的代码

因为第二个问题对我来说是致命的,于是我选择了一种不太优雅但是能解决问题的方式,根据模板和需要生成的组合,生成snippets并在package.json中自动插入对应的路径

let fs = require("fs");
let path = require("path");
// 一个返回模板的函数
const generate = require("./generate-template");
// 生成哪些数据
const CONFIG = require("./generate-data-config");
var cbDataPackage = require("../../package.json");
let preUrl = "./snippets/generate/";

function writeAFile(data, fileName) {
  let str = `export default ${JSON.stringify(generate(data), null, "\t")}`;
  let _path = preUrl + fileName;
  return new Promise((resolve) => {
    fs.mkdir(path.resolve(preUrl), { recursive: true }, (err) => {
      if (err) {
        resolve(err);
      } else {
        fs.writeFile(_path, str, function (err) {
          if (err) {
            console.error("写入文件失败:", err);
          }
          resolve(err);
        });
      }
    });
  });
}

// 生成snippets
CONFIG.forEach((item) => {
  writeAFile(item, `${item}.js`);
});

function writePackageJson() {
  cbDataPackage.contributes.snippets = CONFIG.map((d) => ({
      language: "javascript",
      path: `${preUrl}${d}.js`,
    })
  fs.writeFile("./package.json", JSON.stringify(cbDataPackage), function (err) {
    console.error(err);
  });
}

// package.json注入
writePackageJson();

增加悬浮命令

可以看到把鼠标移动到Promise上后,可以看到一个悬浮框,这个效果是怎么实现的呢?

image.png 我们来根据代码进行分析

// extension.ts
function provideHover(
  document: vscode.TextDocument,
  position: vscode.Position,
  _token: vscode.CancellationToken
) {
  // 当前鼠标悬浮的行
  const line = document.lineAt(position.line).range;
  // 拿到当行所有文本
  const word = document.getText(line);

  // 如果当行中有weather,显示hover
  if (/weather/.test(word)) {
    return new vscode.Hover(
      // 如果要写markdown的话,记得包在MarkdownString中
      new vscode.MarkdownString(
        `更多天气信息请查看\ ${WEATHER_LINK}}`
      )
    );
  }
}
export function activate(context: vscode.ExtensionContext) {
  // 增加subscription
  context.subscriptions.push(
    vscode.languages.registerHoverProvider("javascript", {
      provideHover,
    })
  );
}

增加hover的代码完工了~但是打开调试窗口却没有生效,这是因为activate是有对应的生命周期来去进行触发的,钩子是定义在package.json里,根据查看vscode所有的钩子,我们可以确定要的生命周期为onStartupFinished

"activationEvents": [
    "onStartupFinished"
  ]

现在再进行调试,我们就可以看到出现的悬浮框了!

发布

功能都实现了,可以发布了!现在vscode 发布已经非常简单了,一些教程中使用的Azure生成key已经没有必要了

首先我们需要install vsce

npm install -g vsce
cd # 你的代码路径
vsce package

如果这个时候报了Make sure to edit the README.md file before you publish your extension的错,记得把README中This is the README of your extension这一行删掉

这样子,我们就打出了.vsix文件

在生成.vsix后,我们可以先在本地测试一下,节省打包后有错误的时间成本,双击就可以安装,安装后vscode右下角会提示reload,reload后就可以体验我们的extension了

测试完毕后,我们准备一个microsoft的账号到进入Marketplace aka.ms/vscode-crea…

选择New extension > Visual Studio Code,把.vsix扔进去(这个上传接口经常崩,不知道是不是我网络的问题

image.png

这边需要注意的是,你打包的代码中package.json的publisher得和你Marketplace中的extension name一致

在上传成功后,需要等待3-5分钟,就可以在Marketplace中看到你的应用啦

tips

不要将snippets之类的资源放在src中,放在根目录的snippets文件夹里

虽然乍一看放在src中,再由package.json指过去,调试环境是可以调出snippet的

但是打包后,由于src文件夹在vsix包中是不存在的,所以就自然而然的跪了。。

并且在开发时,找到了一个挺不错的入门教程,提供给大家~ github.com/sxei/vscode…