背景
每次在开发一个新页面的时候,都要从头开始写一些固定的代码,或者每次在写一些特定场景需求的时候,都要从头开始写需要固定的逻辑功能,而这些工作,都是重复的,而不同的开发者,在实现同一功能时,又表现出五花八门的写法,于是,我决定,写一个工具,用来快速生成常用模板,这不仅对于提升效率有所帮助,对于统一规范也有一定的帮助。
当然这个工具可以是cli或者vscode snippets,但个人开发的东西,因为没有太大知名度,使用者主动去用的概率会小一点,于是,我打算开发一个Vscode插件,接下来就是开发过程。
开发过程
一、安装脚手架
环境准备
- NodeJS
- Git
安装
npm install -g yo generator-code
生成项目框架
yo code
根据脚手架提示选择自己的配置,大概如下图所示
# ? What type of extension do you want to create? New Extension (TypeScript) // 使用语言
# ? What's the name of your extension? react-antd-helper // 插件名称
### Press to choose default for all options below ###
# ? What's the identifier of your extension?
# ? What's the description of your extension? 一款快速生成react+antd各种场景的模板插件 // 插件描述
# ? Enable stricter TypeScript checking in 'tsconfig.json'? Yes
# ? Setup linting using 'tslint'? Yes
# ? Initialize a git repository? Yes
# ? Which package manager to use? npm
然后会生成一个“react-antd-helper”的项目,其中主要页面结构如下
|--out // 编译后的输出目录
|-- extension.js
|--src // 核心逻辑
|-- extension.ts // 插件内容写在这里
|--package.json // 发布相关的信息都在这里配置
|--CHANGELOG.md // 发布日志
其中,插件的核心功能都会在extension.ts
中,当你初始化完一个项目后,改文件的内容大概如下
// The module 'vscode' contains the VS Code extensibility API
// Import the module and reference it with the alias vscode in your code below
import * as vscode from 'vscode';
// this method is called when your extension is activated
// your extension is activated the very first time the command is executed
export function activate(context: vscode.ExtensionContext) {
// Use the console to output diagnostic information (console.log) and errors (console.error)
// This line of code will only be executed once when your extension is activated
console.log('Congratulations, your extension "react-antd-helper" is now active!');
// The command has been defined in the package.json file
// Now provide the implementation of the command with registerCommand
// The commandId parameter must match the command field in package.json
let disposable = vscode.commands.registerCommand('react-antd-helper.helloWorld', () => {
// The code you place here will be executed every time your command is executed
// Display a message box to the user
vscode.window.showInformationMessage('Hello World from react-antd-helper!');
});
context.subscriptions.push(disposable);
}
// this method is called when your extension is deactivated
export function deactivate() {}
这里最主要的内容就是
let disposable = vscode.commands.registerCommand('react-antd-helper.helloWorld', () => {
// The code you place here will be executed every time your command is executed
// Display a message box to the user
vscode.window.showInformationMessage('Hello World from react-antd-helper!');
});
注册了一个指令react-antd-helper.helloWorld
,然后做了一个回调。我们可以在里面写我们自己的逻辑,这里我先不冗余写了,不同的插件实现方式也不一样,我会先文章结尾附上我个人插件的源码。
调试
我们直接点击VsCode调试按钮Run Extension
进行调试即可,这时会打开一个新的窗口Extension Development Host(你打开的文件夹)
,然后就可以在这个页面进行调试了
同时,也可以在新打开的页面,输入
command + shift + P
看到我们注册的指令,并执行测试
发布配置
对于VsCode插件来说,插件内容比较灵活,开发内容没有太固定的形式,这里我们就不细说了,而其发布配置,有好多重要的点也是比较通用的点,比较重要,下面我们详细介绍一下发布配置package.json
{
"name": "react-antd-helper",
"displayName": "react-antd-helper", // // 展示名称
"description": "一款快速生成react+antd各种场景的模板插件", // 插件描述
"version": "0.0.7", // 插件版本,可以自己修改,也可以在发布时自动改,生成的插件包会带这个版本
"repository": "https://github.com/sorryljt/react-antd-helper",// 仓库地址
"publisher": "sorryljt", // 发布者
"license": "MIT",
"icon": "logo.png", // 在插件市场展示的插件logo,这里得是一个相对路径的地址
"engines": {
"vscode": "^1.65.x" // 适配的vscode版本,版本过高,将导致低版本vscode安装失败
},
"categories": [
"Other"
],
"activationEvents": [ // 所有的插件中的指令要在这里注册
"onCommand:react-antd-helper.helloWorld",
"onCommand:react-antd-helper.generateSimplePage",
"onCommand:react-antd-helper.generateSearchFormAndTable",
"onCommand:react-antd-helper.generateModal"
],
"main": "./out/extension.js", // 入口文件
"contributes": {
"commands": [ // 指令的详情,可以在 `command` + `shift` + `P`时看到
{
"command": "react-antd-helper.generateSimplePage",
"title": "生成一个简单页面",
"category": "快速生成React&Antd页面"
},
{
"command": "react-antd-helper.generateSearchFormAndTable",
"title": "生成一个表单检索&表格页面",
"category": "快速生成React&Antd页面"
},
{
"command": "react-antd-helper.generateModal",
"title": "生成一个弹窗页面",
"category": "快速生成React&Antd页面"
}
],
"menus": { // 菜单配置
"explorer/context": [ // 文件夹菜单
{
"group": "2_workspace@1",// 决定排序方式,可参考https://www.bookstack.cn/read/VS-Code-Extension-Doc-ZH/docs-extensibility-reference-contribution-points.md#4hamih
"when": "explorerResourceIsFolder", // 执行时机 可参考https://liiked.github.io/VS-Code-Extension-Doc-ZH/#/references/when-clause-contexts
"submenu": "react-antd-helper/submenu/generate" // 可以设置该菜单为子菜单
}
],
"react-antd-helper/submenu/generate": [ // 对应id的子菜单配置,在这里可以配置其对应的指令和排序
{
"command": "react-antd-helper.generateSimplePage",
"group": "1_generate@1"
},
{
"command": "react-antd-helper.generateSearchFormAndTable",
"group": "1_generate@2"
},
{
"command": "react-antd-helper.generateModal",
"group": "1_generate@3"
}
]
},
"submenus": [ // 子菜单的配置,以及其标题显示
{
"id": "react-antd-helper/submenu/generate",
"label": "快速生成一个react&antd页面"
}
]
},
"scripts": {
"vscode:prepublish": "yarn run compile",
"compile": "tsc -p ./",
"watch": "tsc -watch -p ./",
"pretest": "yarn run compile && yarn run lint",
"lint": "eslint src --ext ts",
"test": "node ./out/test/runTest.js"
},
"devDependencies": {
"@types/vscode": "^1.65.0",
"@types/glob": "^7.2.0",
"@types/mocha": "^9.1.1",
"@types/node": "16.x",
"@typescript-eslint/eslint-plugin": "^5.30.0",
"@typescript-eslint/parser": "^5.30.0",
"eslint": "^8.18.0",
"glob": "^8.0.3",
"mocha": "^10.0.0",
"typescript": "^4.7.4",
"@vscode/test-electron": "^2.1.5"
}
}
在上述的package.json
文件介绍中,大部分我通过标记注释的方式来说明用法,这里再特殊说明一下我在开发时候,踩过坑的几个配置项
-
contributes.commands
中注册的指令,要在src/extension.ts
中实现,反之,在src/extension.ts
中实现的指令,也要在其中注册 - 定义指令后,还需要在
activationEvents
中激活"onCommand:react-antd-helper.helloWorld"
- 菜单的配置,我们大部分配置可以官网发布配置中找到,但是其中并没有提起对于资源管理器上下文菜单的子菜单配置,我是通过看其他插件的开发代码找到了配置方法,就像我设置的
submenus
那种 - 关于logo的配置,找了很久,因为默认是不带logo的,并且发布配置中也没有介绍,后来找到了这里https://www.bookstack.cn/read/VS-Code-Extension-Doc-ZH/docs-references-extension-manifest.md
发布插件
插件发布官网提供了比较全的教程,这里做个总结,具体发布看这两篇官网链接就够了
- https://code.visualstudio.com/api/working-with-extensions/publishing-extension#get-a-personal-access-token
- https://www.bookstack.cn/read/VS-Code-Extension-Doc-ZH/docs-working-with-extensions-publish-extension.md
安装vsce
npm install -g vsce
打包成 vsix 文件
vsce package
发布
发布之前,首先你得有一个Personal Access Tokens
按照上面的文档,创建完,可以采用
vsce publish
也可以采用可视化上传vsix文件的方式来发布
发布成功后就可以在扩展市场看到自己的插件了。
遇到的问题
windows系统文件反斜杠的问题
因为我的插件是需要写入文件的,我当时用的是的mac开发,当有些同学试用的时候,发现写入文件失败,后来才发现,我忽略了windows系统下文件路径“\”反斜杠的问题。不能使用node 原生path来获取命令操作路径,在vscode开发环境中,我们不能使用path中的
__dirname
以及path.resolve(./)
来获取操作路径,应该使用registerCommand
方法的回调参数,如下
let generateModal = vscode.commands.registerCommand('react-antd-helper.generateModal', (e) => {
console.log(e) // 其中e为文件信息,但e.fsPath才代表不同操作系统下的真实路径
});
其中e为文件信息,但e.fsPath才代表不同操作系统下的真实路径,所以在拼接文件名时要使用e.faPath
,并且拼接符号的正反斜杠,要使用node path下的sep
变量。这样就可以自动区分出不同系统下的文件路径了,最终可以是这样拼写${fsPath}${nodepath.sep}index.tsx
总结
本文介绍了我个人开发的一个vscode插件的历程,另外也欢迎大家使用我的vscode插件,功能如下
安装了插件后(react-antd-helper),在文件夹出鼠标右击,即可出现如下的菜单
点击生成需要的页面,即可生成例如下面的较完整,可运行的react代码
环境大家使用哦!
也环境大家共建,本插件的源码如下
https://github.com/sorryljt/react-antd-helper