造个vscode插件让工作不再996

6,627 阅读8分钟

每次跳槽换了一个坑位以后就得重新安装各种环境,装个 vscode 还得弄插件,但是 vscode 插件你真的了解吗,今天我们就来聊聊平时开发中用的最多的一种插件,叫做代码片段 snippets ,还可以自己造个插件发布到应用市场。

什么是Snippets

coding小剧场

(情节纯属虚构,如有雷同,算我抄你)

阿强是公司优秀的前端攻城狮,清脆的机械键盘敲击声,微微后移的发际线是他身份的象征,优秀的前端知识体系让他每天处理各种与产品对撕后的需求。

凭借单身二十多年的手速,阿强每次都能踩点deadline完成自己的工作,前端一把手的位置被他牢牢把住。

又是往常的一天,项目组来了一位新的前端攻城狮,名叫阿勇,阿勇的发量惊人,开发代码从来不用机械键盘,浸淫前端可视化多年。

阿强表面波澜不惊,内心却对阿勇的发量相当羡慕,由于就坐在自己后面的桌子,自然而然就对这位新来的前端阿勇产生了兴趣。

过了一周,阿强通过敏锐的观察力发现阿勇上手代码的节奏非常快,不到两天就进入了正式开发阶段。又用两天时间就把这周的功能给开发完了,预发上的绿色通过小图标就是阿勇胜利的象征,期间还偶尔去前台和阿强的女神--阿珍闲聊,这让阿强满头大汉,产生了一丝焦虑。

阿强心里默念:是时候该主动出击了

阿强开始每天给阿珍带爱心早饭,还和阿勇有意无意的展开交流,先从头发的焗油养护开始,再到各类前端框架迭代特性。一周后,阿强终于揭开了阿勇高效率的秘密:

他在vscode里安装了各种 snippets 插件,并且把缩写熟记于心。

阿强迫不及待地装上了 snippets 插件,发现确实事半功倍,抿了一口普洱枸杞茶,眯着眼看着窗外不远处的植发广告,嘴角微微上扬。

代码片段

code snippets 又称代码片段,是用来输入一些已经定义好的模板代码,让coding的过程更加快捷,比如下面这个 tsrfc 就是 typescript react function component 的缩写,后面会有跟着一些描述信息。

snippet_pic1.png

选择下拉的第一个选项就能出现如下图的模板信息。

snippet_pic2.png snippets 也是和开发语言相绑定的,不同的语言可能会有不同的snippets ,比如 computed 参数只会在 vue 中生效, react 是没有的,为了不混淆在一起, vscode 的机制是为不同的语言做不同的映射,在配置内置 snippets 时, vscode 会优先让你选择想要生效的语言。

其实在之前写的文章中就有一个段落(传送门)介绍过在本地的 vscode 开发环境中配置snippets ,这种是最简单的自定义snippets方式,但是也存在一些缺点:

第一个问题在于snippets的配置是一个json文件,下图中 body 只能接受的格式要么是单行的字符串,要么是字符串数组,这样去复制粘贴常用代码过来的时候还得做一轮格式转换。

snippet3.png

第二个问题是如果我换了一台机器去开发,那我积累的一些模板配置就要重新录入了,而且不同的语言还得做区分,迁移起来非常麻烦。

插件市场

vscode 的插件市场非常的丰富,在里面不仅能找到一些常规的语言高亮,主题支持,代码检查等开发插件,还能刷刷leetcode,打打小霸王划划水🐶。

所以用 vscode 插件的方式来维护snippets是非常不错的方式,在 vscode 的插件市场里面有各种语言的snippets支持,下面就是搜索的结果。

snippets.png

比如点开一个 react 相关的snippets插件,在它的细节描述里就会有各种 prefix 对应的模板信息列表,使用熟练后就能记住一些缩写。

snippet5.png

除了上图展示的这个 react snippets 外,下面根据我自己的开发经验列出了几个前端常用的 snippet :

  1. HTML Snippets

支持所有 HTML5 特性

snippets6.png

搜索关键词:`html-snippets

  1. JavaScript (ES6) code snippets

支持 ES6 语法的js插件

snippets7.png

搜索关键词:javascriptsnippets

  1. Vetur

强大的 Vue 插件,不仅有 snippets ,还有各种语法高亮,格式校验等

snippets8.png

搜索关键词:vetur

  1. Ant Design Snippets

你没看错, antd 也有自己的 snippets 

snippets9.png

搜索关键词:antd-snippets

  1. Flutter Widget Snippets

Flutter 的内置组件非常多,用 snippets 的方式去管理是个不错的选择

snippet10.png

搜索关键词: flutter-snippets

自定义插件

使用插件市场的插件基本上都是比较通用的,也就意味着需要一个映射的列表来查看对应的模板代码,但是如果没有在插件市场找到自己需要的snippets插件,那么就可以自己来造个插件并发布,这样子既不担心换环境的问题,也不用可以去记一些 prefix 。

step1 安装脚手架并搭建项目

npm install -g yo generator-code // 安装全局脚手架
yo code // 运行脚手架

这个脚手架运行后需要填一些配置,比如选择哪种类型的插件,如下图所示,这里需要选择 New Code Snippets ,然后就是一些 name , description , language 等信息

snippets11.png 全部配置走完后就会生成一个可立马开发调试的项目,项目的结构和我们平时前端开发的 npm 模式误差,开发的语言也是ts或者js,如下图所示: snippets12.png

按下 F5 就会进入新开启一个窗口,这个窗口就是调试用的IDE,在里面写代码就会生效 snippets 配置。

step2 配置snippets

查看项目的 package.json 就会发现有个 contributes.snippets 属性,里面有语言和相关snippets配置的映射,点开 snippets.code-snippets 文件就会发现这是一个空的json文件,要写内容的话,里面的格式和上文提到的JSON配置一模一样。

那么问题来了,这样其实还是在配置这个json文件,上文提到的 body 问题还是没解决,配置起来还是挺麻烦的,客官莫慌,这里其实可以写一个脚本语句进行转换我们正常的代码。

首先,我看下目录的结构, example 路径下全是模板代码, snippets.json 是我最终输出的json文件,核心的转换脚本代码在 compiler.js 里。

snippets13.png

reactuseCallback 举个🌰,首先三行是额外的注释信息,在配置中做转换,下面的代码就是模板内容了,${}包裹的代码说明是可编辑的模板字符串,冒号后面是默认值,数字代表编辑的顺序,比如 memoizedCallback 编辑完按Tab键就到下一个 doSomething

snippets16.png

compiler.js如下:

const fs = require('fs')
const path = require('path')

// example 目录的绝对路径
const exampleDir = path.resolve(__dirname, 'example')
// 输出json配置目录
const outputDir = path.resolve(__dirname, 'snippets')

// 初始化代码片段json
const snippetsMap = {}

const readDir = (rootDir) => {
  const fileList = fs.readdirSync(rootDir)
  if (fileList.length > 0) {
    fileList.forEach(fileName => {
      const filePath = path.join(rootDir, fileName)
      const statInfo = fs.statSync(filePath)
      // 如果是目录继续遍历
      if (statInfo.isDirectory()) {
        readDir(filePath)
      } else if (statInfo.isFile()) {
        handleFile(filePath, fileName)
      }
    })
  }
}

// 处理文件
const handleFile = (filePath, fileName) => {
  let name = fileName.split('.')[0]
  let prefix = fileName.split('.')[0]
  let des = ''
  const bodyList = []

  const fileInfo = fs.readFileSync(filePath, 'utf8')
  const lineSplits = fileInfo.split('\n')

  // 逐行区分,对名称,描述,prefix做提取处理
  lineSplits.forEach(line => {
    const nameReg = /\/\/\s+@name:\s*(.*)/
    const prefixReg = /\/\/\s+@prefix:\s*(.*)/
    const desReg = /\/\/\s+@description:\s*(.*)/
    if (nameReg.test(line)) {
      name = line.match(nameReg)[1]
    } else if (prefixReg.test(line)) {
      prefix = line.match(prefixReg)[1]
    } else if (desReg.test(line)) {
      des = line.match(desReg)[1]
    } else {
      bodyList.push(line)
    }
  })

  snippetsMap[name] = {
    prefix,
    body: bodyList.length > 1 ? bodyList : bodyList[0],
    description: des
  }
}

readDir(exampleDir)

fs.writeFile(path.join(outputDir, 'snippets.json'), JSON.stringify(snippetsMap, null, 2), (err) => {
  if (err) throw err;
  console.log('write success')
})

compiler.js做了几件事情:

  • 遍历 example 下的所有文件
  • 提取一些注释信息并当做 name 或者 description 
  • 输出写入进 snippets.json 

step3 发布插件

发布插件需要用到一个命令行工具--- vsce 

npm install -g vsce

我这边的方式是打包成一个 .vsix 文件进行上传,打包命令如下

vsce package

打完包去 Azure 的官方控制台上传即可

snippets14.png

Azure 可能需要先新建一个组织,可以参考以下文档:

传送门

我这边就维护了一个和 react 相关的 snippets 插件,关键词搜索 react-tsx-hooks-snippets 就能找到:

snippets15.png

欢迎大家在github上给我提issue进行改进~~

github项目地址:github.com/Tinsson/rea…

结束

snippets是帮助我们效率提高的一种手段,效率提高了才能摆脱996,希望大家在工作中灵活使用,沉淀出自己的snippets插件。

创造不易,希望掘有多多 点赞 + 关注 二连,持续更新中!!!

PS: 文中有任何错误,欢迎掘友指正

往期精彩📌

公众号:前端小DT

参考文章📚: