构建 VS Code Extension,提高 Flutter 开发效率(二):从零开始

1,042 阅读4分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第3天,点击查看活动详情

承接上文:

《构建 VS Code Extension,提高 Flutter 开发效率(一)》

前言

笔者很少写基础的东西,主要原因是掘金上很多大佬都写的很好了。但日新计划你懂得,只写设计架构和思想基本就快被榨干了。

所幸,关于如何写 VS Code Extension 的文章更多的是更基础的搭建和 API 介绍等,讲实战的很少,那这篇从0开始讲起,把上一篇介绍的能力是如何实现的一一拆解介绍给大家。

起步

初始化工程

(略)

基本按照网上的教程来就行了 npm install -g yo generator-code,微软的东西入门都非常快,这里就不水字数了。

package.json

这个需要着重讲一下,毕竟 package.json 配置好了项目就完成了一半[手动狗头]。

网上的很多说明只相当于官网文档的翻译,真正还是要自己摸索才可用,那这里把笔者觉得重要的说明直接写在注释上:

{
  "name": "gaoding-flutter-components-kit",
  "displayName": "Gaoding Flutter Develop Kit", // 显示的名称
  "icon": "assets/icon.png", // 显示的图标,这里官方推荐是用在线地址,但这里用相对路径也可以
  "keywords": [ // 搜索关键字
    "Gaoding",
    "flutter"
  ],
  "activationEvents": [ // 扩展触发的事件,相当于一个插件启动监听
    "onLanguage:dart", // 在 `dart` 文件中启动
    "onLanguage:yaml", // 在 `yaml` 文件中启动
    "onStartupFinished" // 在 VS Code 加载完成后启动(推荐)
  ],
  "contributes": { 
    "commands": [ // 各种命令配置
      {
        "command": "gaoding-flutter-components-kit.runGenerateAPI", // 命令,代码里通过这个流转
        "title": "run generate api", // 标题和分类都是用于界面选择的
        "category": "GaodingFlutter",
        "icon": { // 这里的图标是用于下面的 toolbar 配置的
          "light": "assets/light/icon.svg",
          "dark": "assets/dark/icon.svg"
        }
      },
      ...
    ],
    "menus": {
      "editor/title": [ // 这里就是配置上篇文章中的 toolbar 便捷按钮
        {
          "when": "resourceFilename == ui_components.yaml", // 判断当前打开的文件是否是 ui_components.yaml,可以用正则
          "command": "gaoding-flutter-components-kit.runGenerateAPI", // 执行哪一个命令
          "alt": "",
          "group": "navigation" // 按钮放在哪个组内
        }
      ]
    }
  },
  "scripts": {
    ...
    "publish": "vsce publish" // 使用 vsce 发布到公仓
  },
  ...
  "extensionPack": [ // 这里就是用于配置依赖包,下载你的扩展会同事下载下面配置的,这样做开发环境集成
    "dart-code.flutter",
    "marufhassan.flutter-snippets",
    "eamodio.gitlens",
    "kisstkondoros.vscode-gutter-preview",
    "davidanson.vscode-markdownlint",
    "esbenp.prettier-vscode",
    "redhat.vscode-yaml"
  ]
}

src/extension.ts

src/extension.ts 是项目的入口文件,相当于 main.ts

最关键方法就是 activate 就是 package.jsonactivationEvents 触发事件后执行的方法。我们可以把启动直接触发和命令触发的方法也到这里面。

export function activate(context: vscode.ExtensionContext) {
  // 注册命令执行方法
  registerCommands(context);
  // 启动后执行检查
  validAPIChange.excute(context);
}

这里看了很多 Extension 源码,发现大家普遍喜欢把 activate 写很长(没错,说的就是你 dart 源码传送门,你的 activate 圈复杂度都炸了,你难道不知道吗[手动狗头]),但还是符合单一职责更易维护。

再放一下 registerCommands 的实现,其实很简单:

function registerCommands(context: vscode.ExtensionContext) {
  context.subscriptions.push(
    vscode.commands.registerCommand(
      'gaoding-flutter-components-kit.runGenerateAPI', // package.json 里面定义的命令
      () => {
        generateAPI.excute(context); // 命令触发,想要执行的方法
      }
    )
  );
  ...
}

这样就插件就可以上路了,调试也很简单,直接使用 VS Code 自带的 run/start debug,就会新开一个 VS Code 窗口进行调试。

常用的 API

这里简单介绍下笔者常用的 VS Code API

UI 展示

  1. 提示框
/// 显示一个错误提示框
vscode.window.showErrorMessage( 
  'GaodingFlutter: application_services 找不到',
  {
    modal: true,
    detail: 'Please check your workspace.',
  }
);

还有 vscode.window.showInformationMessage 消息提示框等,不一一列举

也可以增加自定义按钮

let result = await vscode.window.showInformationMessage(
  'GaodingFlutter: 生成文档路径未配置',
  '去配置'
);
if (result === '去配置') {
  ... 
}

(说实话它只能通过按钮文字来判断返回流转,有点粗暴但确实简单)

  1. 显示带个进度的通知栏,flutter pub get 展示的那种
vscode.window.withProgress(
    {
      location: vscode.ProgressLocation.Notification, 
      title: 'GaodingFlutter: excuting `flutter pub get` on workspace',
      cancellable: true,
    },
    async (_, token) => {
      // 取消按钮点击回调
      token.onCancellationRequested(() => {
        ...
      });
    ...
    }
)
  1. 打开一个文件选择对话框

vscode.window
  .showOpenDialog({
    title: `请选择 ${projectName} 项目路径`,
    canSelectFolders: true,
    canSelectFiles: false,
    canSelectMany: false,
  }).then((uri) => { ... });

功能 Control

  1. 运行一个 Debug, 相当于执行下图的功能
image.png
await vscode.debug.startDebugging(undefined, { // 这里面的 json 相当于 debug 的 launch.json
  name: 'Flutter: Attach to Device',
  request: 'attach', 
  type: 'dart'
});
  1. 在界面上直接打开一个文件
vscode.commands.executeCommand('vscode.open', vscode.Uri.file(file: string));
  1. 本地缓存
context.globalState.setKeysForSync(key);

context.globalState.update(key, value);

context.globalState.get(key);

一个简单的 KV 缓存

剩下的不多水字数了,API 都可以在官方文档搜到。

总结

扩展开发上手难度不高,微软的东西集成度又很高,只要有想法,能做很多事,比如提供一个简单的扩展只配置 extensionPack 来整合整个项目的开发环境,多做一步可以统一配置 settings.json,让团队开发规范趋于统一。

但文章是比较少的,学习上通过 google baidu 找资料,不如去看常用扩展的源码,找到了基本就能拿来即用,但有些实现上写的也是蛮糟糕的,从头开始看不如带着关键字去 git 中搜效果更好。

image.png

如果对你开发学习上有丝丝作用,请点个赞[开心] ~