乐趣区

关于前端:前端工程化VSCode插件集成脚手架和组件库

<!– START doctoc generated TOC please keep comment here to allow auto update –>
<!– DON’T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE –>
Table of Contents generated with DocToc

  • 前端工程化 -VSCode 插件集成脚手架和组件库

    • 前言
    • VSCode 插件能做什么
    • VSCode 可扩大能力

      • 基于 Electron 能力
      • 可扩大能力
      • 扩大工作台
      • 扩大编辑器
      • 限度
    • 开发插件

      • 初始化我的项目
      • 集成 Webview
      • 提供 Webview 内容
      • Webview 和 VSCode 通信
      • 国际化

        • 配置项国际化
        • VScode 代码国际化
        • Webview 代码国际化
    • VSCode 插件集成基建

      • AppWorks
      • FAW 应用成果
      • FAW 整体架构
      • FAW 新建我的项目

        • 外围流程
        • 外围代码实现
      • FAW 新建物料

        • 外围流程
        • 外围代码实现
      • FAW 新建组件
      • 小结
    • 常见插件实现原理

      • JSSnippet
      • WordCount
      • TODOTree
      • Vetur
    • 总结
    • 援用

<!– END doctoc generated TOC please keep comment here to allow auto update –>

前端工程化 -VSCode 插件集成脚手架和组件库

前言

转载自搜狐 - 前端工程化 -VSCode 插件集成脚手架和组件库

<!– VSCode是微软出的一款轻量级代码编辑器,收费而且功能强大,对 JavaScriptNodeJs反对十分敌对。并且提供插件机制,VSCode很多弱小性能都是基于插件实现,比方代码格式化、代码智能补全等。–>

咱们程序员每天的产出大部分都是在 IDE 中实现,大家在日常开发过程中,多多少少会有些本人的非凡定制需要去晋升开发效率,比方写 shell 脚本、浏览器插件等,在 Visual Studio Code (VSCode) 中咱们也能开发一些插件去满足日常工作须要。

比方当初业务要新开发一个我的项目,设计稿格调和之前零碎相似。那我第一想法必定是去拷贝已有我的项目的代码(或者应用组内形象的模板),而后稍作批改满足以后需要。但如果是新同学往往须要经验 征询已有我的项目 / 模板相干人员 -> 开明各种权限 -> 复用局部代码并做个性化批改 -> 借助组件库、工具库进入业务性能开发,这个过程有肯定沟通和工夫老本。

所以我冀望能有一个更直观的形式让新同学理解组内有哪些基建并投入使用,比方能间接在 VSCode 中列举以后的模板我的项目,预览后抉择特定模板进行我的项目初始化,并且将一些个性化根底配置通过表单模式进行填写并渲染,防止脱漏。而且在开发过程能在 VSCode 中直观的展现以后有哪些组件和工具函数能够应用,而后通过点点点操作实现组件的增加和疾速应用。

本文也将带着上面几个问题去解说开发 VSCode 插件的过程

  • VSCode插件能做什么?
  • 如何开发一款 VSCode 插件?
  • VSCode中如何嵌入webview
  • VSCode中如何配置国际化?
  • VSCode插件中如何新建我的项目、新建页面、组件 …?

VSCode 插件能做什么

目前罕用 VSCode 插件可分为上面几大类

  • 语言类插件

    • 语法高亮(Vetur)
    • 代码主动补全(TabNine)
    • 代码片段(JS JSX Snippets)
  • 工具类插件

    • 可视化搭建页面(面向开发者的低代码)(AppWorks)
    • 工夫治理(WakaTime)
    • Git 治理(Git Graph)
    • TODO(TODO Tree)
  • 娱乐类插件

    • 听音乐(VSC Netease Music)
    • 炒股(韭菜盒子)
    • 玩游戏(小霸王)

VSCode 可扩大能力

本章大部分内容在官网中已有阐明,此处做一个简略解说

VSCode 提供哪些能力去实现上一章所提到的成果?

基于 Electron 能力

VSCode自身是应用 Electron 开发的,那他也反对对应的能力。

  • 反对读取本地文件
  • 反对发送承受跨域申请
  • 反对创立本地服务器
  • 长久化存储本地数据

可扩大能力

  • 应用色彩或文件图标主题更改 VSCode 外观
  • UI 中增加自定义组件和视图
  • 创立 webview 以显示应用 HTML/CSS/JS 构建的自定义网页
  • 反对一种新的编程语言
  • 反对调试特定运行时

扩大工作台

VSCode 提供了各种 API,容许您将本人的组件增加到 工作台

  • 流动栏(Tree View Container):Azure 应用服务扩大增加了一个视图容器
  • 侧边栏(Tree View):内置的 NPM 扩大在 Explorer 视图中增加了一个树视图
  • 编辑器组(Webview):内置的 Markdown 扩大在编辑器组中的其余编辑器旁边增加了一个 Webview
  • 状态栏(Status Bar):VSCodeVim 扩大在状态栏中增加了一个状态栏项

扩大编辑器

  • 基于正则编辑页面中的内容

    • 例如:删掉以后页面所有正文或log
  • 自定义跳转、主动补全、悬浮提醒

    • 例如:输出 rfc 主动补全代码
  • 对特定后缀名文件的解析和编辑

    • 例如:借助插件 vetur 解析 .vue 文件
  • 加强 VSCode 内置的 MD 预览和 Git 工具

    • 例如:丑化预览 .md 文件

限度

于此同时,也存在一些限度,比方插件不能访 问VSCode UI 的 DOM 节点(如果强行改变,VSCode 会提醒本身损坏)

开发插件

首先对 VSCode 插件能力有个大略意识,而后从 HelloWorld 初始化我的项目 去入门,再去集成Webview

因为 VSCode 自身是应用 Electron 开发的,且 Electron 是基于 Chromium,渲染过程是应用Web 页面作为 UI 显示。那在 VSCode 中也能集成webview

初始化我的项目

npm i -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? HelloWorld
## Press <Enter> to choose default for all options below ###

? What's the identifier of your extension? helloworld
? What's the description of your extension? LEAVE BLANK
? Initialize a git repository? Yes
? Bundle the source code with webpack? No
? Which package manager to use? npm

? Do you want to open the new folder with Visual Studio Code? Open with `code`

页面要害构造如下

.
├── package.json # 插件配置
├── src
│   ├── extension.ts # 入口文件
├── tsconfig.json

package.json要害内容如下

{
  // 扩大的激活事件
  "activationEvents": ["onCommand:extension.sayHello"],
  // 入口文件
  "main": "./src/extension",
  // 奉献点,vscode 插件大部分性能配置都在这里
  "contributes": {
    "commands": [
      {
        "command": "extension.sayHello",
        "title": "Hello World"
      }
    ]
  }
}

src/extension.ts要害内容如下

const vscode = require('vscode');
// 插件被激活时触发,所有代码总入口
exports.activate = function(context) {
  // 注册命令 与 `package.json` 中 `contributes.commands`
  context.subscriptions.push(vscode.commands.registerCommand('extension.sayHello', function () {vscode.window.showInformationMessage('Hello World!');
  }));
};
// 插件被开释时触发
exports.deactivate = function() {};

而后在编辑器中按 F5 即可关上新的窗口在命令面板中(⌘⇧P)运行 Hello World 命令进行调试插件

集成 Webview

下方示例为在 VSCode 集成通过 ice 生成的webview

  1. 创立 web 目录初始化我的项目

    mkdir web
    cd web
    yarn create ice
    # or
    yarn create @umijs/umi-app

集成umijsoricejs,上面我的项目将以 ice 为例

  1. 配置 package.json 注册 激活事件

    {"activationEvents": ["onCommand:project-creator.create-project.start"],
      "contributes": {
     "commands": {
       "command": "project-creator.create-project.start",
       "title": "创立我的项目 webview"
     }
      }
    }
  • activationEvents字段值为数组,通过 onCommand 注册激活事件 project-creator.create-project.start,而project-creator.create-project.start 将在 contributes.commands 中定义
  • contributes字段能够配置扩大 VSCode 各种能力,比方commands 命令configuration 配置

    • commands中的 command 将在 src/extension.ts 中进行注册事件回调
  1. 配置 src/extension.ts 创立 webview 的具体逻辑
  • 注册命令project-creator.create-project.start
  • 创立 webview 面板projectCreatorWebviewPanel

    • 如果有,则间接展现
    • 如果没有,则新建
  • 配置根本配置

    • 题目
    • 启用JavaScript 脚本
    • 暗藏时保留上下文
    • 图标
  • 设置 webview 面板内容
  • 提供 webviewvscode 交互

VSCode中的 Webview 实质就是一个 iframe,所以是能够在其中执行 脚本 ,然而VSCode 默认禁用 JavaScript,所以须要配置enableScripts=true 开启此性能。

提供 Webview 内容

通过 getHtmlForWebview 获取 webview 的内容。

因为应用 icejs 进行构建我的项目,yarn build后的目录构造为index.html、css/index.css、js/index.js,如果开启MPA,则还有vendor.css/js

如果应用其余框架比方 umijs,则采取不同的解决形式即可。

其中通过 getNonce 生成一个随机数,设置到 scriptnonce属性,作用是在加密通信中应用一次随机数防止反复攻打,保障不同的音讯与该秘钥加密的秘钥流不同。此代码拷贝自 VSCode 提供的官网示例。

Webview 和 VSCode 通信

一个很常见的场景,咱们在 webview 中通过 调接口 获取数据,而后渲染页面。然而在 vscode webview 中是不容许发送 ajax 申请,所有申请都是跨域(因为 webview 自身没有 host),所以须要在VScode 中进行实在的接口申请。

此过程则变为在 Webview 端应用 vscode.postMessage,而后在VScode 中应用 webview.onDidReceiveMessage 接管到音讯后做相应解决。

将交互过程封装成 connectServicecallService进行对立注册和调用。

  • 能够在 VSCode 端创立 Webview 时绑定 connectService,在其中监听webview 接管到的音讯,而后调用 VSCodeapi能力,将执行后果返回给 Webview
  • Webview 中调用 callService,而后将事件和参数传递给connectService 解决,也将处理结果传给回调函数。

options 中提供以后页面须要应用的所有服务 services 的定义,而后再接管到调用事件时,通过 const api = services && services[service] && services[service][method] 获取到具体的办法,并将参数进行传递,肯定水平去抹平 API 的差别,缩小反复代码量。

国际化

VSCode的国际化次要有三局部组成

  • 配置项 国际化
  • VScode代码国际化
  • Webview代码国际化
配置项国际化

咱们能够在 package.json 中配置 VSCode 的配置项,这些配置项的国际化是约定在 package.nls.jsonpackage.nls.zh-cn.json这些文件中。

比方能够在 package.nls.json 中配置插件英文名称

{"projectCreator.create-project.commands.start.title": "Select Scaffold to Create Application"}

package.nls.zh-cn.json 中配置插件中文名称

{"projectCreator.create-project.commands.start.title": "抉择模板创立利用"}

而后在 package.json 中应用

"contributes": {
  "commands": [
    {
      "command": "project-creator.create-project.start",
      "title": "%projectCreator.create-project.commands.start.title%"
    }
  ]
}
VScode 代码国际化

国际化的解决思路都一样

在代码中进行注册,并且能够通过 vscode.env.language 获取 VSCode 以后语言环境。

import * as vscode from 'vscode';
import I18nService from './i18n';
import * as zhCNTextMap from './locales/zh-CN.json'; // {"webViewTitle": "Create Project"}
import * as enUSTextMap from './locales/en-US.json'; // {"webViewTitle": "创立我的项目"}

// 注册语言表
const i18n = new I18nService();
i18n.registry('zh-cn', zhCNTextMap);
i18n.registry('en', enUSTextMap);

// 设置应用的语言
i18n.setLocal(vscode.env.language);

export default i18n;

而后在代码中进行应用

projectCreatorWebviewPanel = vscode.window.createWebviewPanel(
  'project-creator', // webview 标识,只供外部应用
  i18n.format('webViewTitle'), // 题目
  vscode.ViewColumn.One, // 新开一个编辑器视图
  {
    enableScripts: true, // 启用 JavaScript 脚本
    retainContextWhenHidden: true, // 暗藏时保留上下文
  },
);
Webview 代码国际化

Webview 中咱们采纳 icejs 搭建我的项目,那就能够应用 react-intl 来配置国际化。

而后在代码中进行应用

VSCode 插件集成基建

前端同学在开发过程中个别会经验但不限如下过程

  • 开发筹备阶段:需要评审,查阅内部或组内知识库、开发标准
  • 编码 & 联调阶段:按需要场景依据内部或组内脚手架、组件库、工具库 … 进行编码调试
  • 调式优化阶段:数据埋点、性能优化、自动化测试 …
  • 构建部署阶段 :大部分企业都有自研的devops 解决方案
  • 上线后数据采集 & 分析阶段:进行性能监控、报警、数据分析 …
  • 技术积淀:对上述过程进行复盘、总结、形象,进入下一轮需要开发

当咱们进入一个新团队时,往往冀望能对团队外部的 前端研发全链路 有一个根本意识,进而能够疾速进入开发或投身到感兴趣的技术建设。

当咱们开发一个新我的项目时,往往冀望能参考老我的项目看是否能复用局部,进而缩小不必要的重复性工作。

基于下面章节对 VSCode 插件所提供的能力介绍,咱们齐全能够将 前端研发全链路 的基建集成到咱们日常编码 IDE 中,并且提供可视化的操作界面,让咱们能安心在 IDE 中进行开发调试,从肯定水平缩小咱们开发过程 到处检索 而分心低效的问题。

AppWorks

AppWorks 是一款基于 VSCode 插件的前端研发工具集,通过 GUI 操作、物料组装、代码辅助等性能让前端开发更加简略。

不过因为上面几个起因,咱们决定基于 AppWorks 做个性化革新以便满足部门外部应用。

  • 他对 icejsRax 类型我的项目反对敌对,但因为咱们部门中后盾我的项目技术选型为 umijs,在应用AppWorks 时面板内容显得有点冗余。
  • 并且咱们我的项目应用 微前端 架构,在 slave 我的项目中不少配置是冀望在初始化模板时就主动配置好。
  • 物料 方面咱们有本人一套组件库并且放在公有npm,自定义物料的形式也冀望能保留咱们以后发包构造

    • 物料:分为组件(component)、区块(block)和我的项目(scaffold)三种类型

基于上述思考,咱们做了二次开发并产出了FAW,上面将从应用成果去揭秘他的外围逻辑实现。

FAW 应用成果

上面示例为新建一个 微前端子利用 的场景

  • 1 通过点击侧边栏激活创立我的项目流程
  • 2 抉择具体模板后点击下一步
  • 3 输出项目名称、模板版本
  • 4 如果模板提供 ask-for-vscode.js 文件,则依据配置生成表单

    • 次要是配置publicPathbasePathmountElementIdid
  • 5 表单填写结束后点击实现
  • 6 生成我的项目后在以后窗口关上新我的项目,即可进入开发

FAW 整体架构

依据开发插件章节,能够将 模板抉择、填写配置 这些交互性能放在 展现层 webview中实现,而将 获取模板、拷贝模板并渲染 这些性能交由 业务层 VSCode实现。

于此同时能够在入口 AppWorks 中“捆绑”组内高频应用插件,实现装置一个插件时能够装置一系列插件。

并且将一些 公共配置项、国际化、创立我的项目和创立物料的外围逻辑...放入 packages 中应用 lerna 做治理并在插件中应用。

物料 根本信息放在 配置平台 中做对立配置;我的项目模板 寄存在 Gitlab 做版本治理;组件库 放在 公有 npm做治理。

FAW 新建我的项目

逻辑相似前端工程化 - 打造企业通用脚手架 -focus create projectName 外围流程

外围流程
  • 1 点击“创立利用”,唤起 webview 页面
  • 2 从 配置核心 拉取所有“我的项目模板”列表
  • 3 抉择“具体模板”后,拉取所有版本(版本默认约定为在 Gitlab 端打的tag
  • 4 抉择“具体版本”后,判断以后模板是否提供 ask-for-vscode.js 文件
  • 4.1 如果没提供则对本模板本版本做本地缓存,不便下次应用。则进入第 6 步
  • 4.2 如果提供则依据配置项渲染为表单供开发者填写

    • 配置项个别为publicPathbasePathmountElementIdid
  • 5 通过 ncp 把代码拷贝到本地长期目录,而后依据 4.2 填写的内容渲染变量在 ejs 模板,最初通过 metalsmith 遍历所有文件做插入批改
  • 6 关上新窗口并启动以后我的项目
  • 7 实现,开始进入代码编写
外围代码实现

其中 第 2 步 定义 模板物料 的构造,而后在配置平台保护一个 json 寄存所有模板

第 3 步 中抉择具体模板后拉取所有版本,次要借助 Gitlab 提供的凋谢能力 https://docs.gitlab.com/ee/api/api_resources.html

第 4 步 中抉择具体版本后,拉取对应代码,并判断是否存在 ask-for-vscode.js 文件并解析其内容

因为 require 须要以require(/Users/${filename}.js) 的模式导入绝对路径 + 变量,然而咱们模板的名字以及配置都名为变量,故获取不到。

// 此形式可行 ✅
const code = require('/Users/careteen/Desktop/admin-umi-template/ask-for-vscode.js')
// 此形式不可行 ❌
const templateName = 'admin-umi-template'
const configName = 'ask-for-vscode'
const args = require(`/Users/careteen/Desktop/${templateName}/${configName}.js`)

所以此处采纳 readFileSyncnew Function(code)()的形式获取 js 文件内容。其中内容如下:

// 须要依据用户填写批改的字段
const requiredPrompts = [
  {
    type: 'input',
    name: 'repoNameEn',
    message: 'please input repo English Name ? (e.g. `smart-phone`.focus.cn)',
  },
  {
    type: 'input',
    name: 'repoNameEnCamel',
    message: 'please input repo English Camel Name ?(e.g. smart-case.focus.cn/`smartPhone`)',
  },
  {
    type: 'input',
    name: 'repoNameZh',
    message: 'please input repo Chinese Name ?(e.g. ` 智能话机 `)',
  },
];
return {requiredPrompts,};

用这部分内容渲染成表单,而后再依据用户输出内容渲染 ejs 模板,比方配置文件config/config.ts

// 模板 👉
export default defineConfig({
  title: '<%=repoNameZh%>',
  manifest: {basePath: '/<%=repoNameEnCamel%>/',},
  base: '/<%=repoNameEnCamel%>/',
  outputPath,
  publicPath: '/<%=repoNameEnCamel%>/',
  mountElementId: '<%=repoNameEnCamel%>',
  qiankun: {slave: {},
  },
});
// 渲染后 👇
export default defineConfig({
  title: '智能话机',
  manifest: {basePath: '/smartPhone/',},
  base: '/smartPhone/',
  outputPath,
  publicPath: '/smartPhone/',
  mountElementId: 'smartPhone',
  qiankun: {slave: {},
  },
});

第 5 步 中进行拷贝和批改插入

最初 我的项目生成胜利后在窗口中关上新生成的我的项目

FAW 新建物料

  • 1 通过命令 FocusWorks: Generate Page by Blocks 唤起 新建页面 的页面
  • 2 在面板右侧增加组件,能够在左侧进行拖拽布局
  • 3 点击 生成页面 并输出页面名称和路由配置
  • 4 点击实现后生成页面
外围流程
  • 0 上面示例为在 umi 类型我的项目中新增一个 列表页
  • 1 命令行唤起 webview 页面
  • 2 判断当前工作区的我的项目类型,而后从 配置核心 拉取所有“组件”列表
  • 2.1 须要保护多套组件库并提供 demo 示例
  • 2.2 先从依赖项中判断是否有umi,没有再判断是否有React,没有再判断是否有Vue
  • 3 增加组件后借助 react-sortable-hoc 反对拖拽布局
  • 3.1 只反对纵向排列,因为组件粒度都较大,横向不好布局
  • 4 填写页面名称(PageName)和路由配置(pageName)
  • 5 从 npm 中下载具体组件 tgz 到本地长期目录并解压
  • 5.1 而后将 src/demo 内容拷贝到 第 4 步 中所填写的页面地址的 components 目录下
  • 5.2 并在 PageName/index.tsx 中插入援用组件的代码
  • 6 判断是否须要解决路由配置
  • 6.1 如果没获取到 config/route.ts 文件则不须要配置路由,进入 第 7 步
  • 6.2 如果须要配置,则会读取 config/route.ts 文件内容,并插入一条路由配置
  • 7 删除 第 5 步 中下载到长期目录的文件
  • 8 实现
外围代码实现

第 2 步 中须要判断以后我的项目类型,好精确的获取对应的组件库列表。

页面物料 的构造如下,粒度个别较大,比方中后盾最常见的 面包屑 + 筛选项 + 操作栏 + 列表 + 分页 页面

第 3 步 应用 react-sortable-hoc 来反对组件的拖拽布局。

第 5 步 当点击实现时,生成页面 配置路由

生成页面 的流程如下

  • 5.1 将组件下载到本地 src/pages/PageName/components/ 目录下
  • 5.2 筹备 src/pages/PageName/index.tsx 页面入口模板,并写入组件援用代码
  • 5.3 生成 src/pages/PageName/index.tsx 文件

5.1将组件下载到本地 src/pages/PageName/components/ 目录下

  • 5.1.0 筹备组件库
  • 5.1.1 先下载到本地长期目录.temp-block
  • 5.1.2 将组件拷贝到以后我的项目的 pages/PageName/components/ 目录下
  • 5.1.3 删除长期目录的文件
  • 5.1.4 主动装置组件的依赖

5.1.0 筹备组件@focus/pro-concise-table,组件 demo 寄存在@focus/pro-concise-table/src/demos/index.tsx

5.1.1先下载到本地长期目录.temp-block

其中获取组件压缩包地址次要应用 package-json 实现,下载 tgz 并解压内容则借助request-promise、zlib、tar

5.1.2 将组件拷贝到以后我的项目的 pages/PageName/components/ 目录下。

5.1.4 主动装置组件的依赖

第 6 步 如果须要配置路由,在创立路由时须要判断以后我的项目类型 umi/react/vue,上面的逻辑次要是解决umi 类型我的项目

创立 umi 类型我的项目路由外围逻辑次要是依据第 第 4 步 中填写的 页面名称、路由、父级页面 做解决。

  • 6.1 读取我的项目 config/routes.ts 文件内容并应用 @babel/parser.parse 将代码解析为AST
  • 6.2 借助 @babel/traverse 遍历 第 6.1 步 AST判断获取所有路由配置的 数组 模式
  • 6.3 将新增的路由信息拼接到 第 6.2 步 数组 开端
  • 6.4 对路由解决后从新笼罩 config/routes.ts 文件

6.1 读取我的项目 config/routes.ts 文件内容并应用 @babel/parser.parse 将代码解析为AST

6.2 借助 @babel/traverse 遍历 第 6.1 步 AST判断获取所有路由配置的 数组 模式

6.4 对路由解决后从新笼罩 config/routes.ts 文件,此处为对 umi 类型我的项目解决,应用 @babel/* 做代码替换演示。

FAW 新建组件

  • 1 通过命令 FocusWorks: Import Component 或在编辑器右上方题目菜单栏中点击“+”唤起 新建组件 的页面
  • 2 将鼠标搁置在冀望新增组件的中央,点击组件的“增加”
  • 3 即可插入组件信息,并主动拷贝组件 demo、装置依赖

实现的思路大部分同 FAW 新建物料,上面将重点介绍不一样的中央

  • 1 如果以后有激活的文件,则在右侧唤起webview
  • 2 能够在 contributes.menus.editor/title 中扩大编辑器题目菜单栏
  • 3 在鼠标光标处插入组件代码

1如果以后有激活的文件,则在右侧唤起webview

2能够在 contributes.menus.editor/title 中扩大编辑器题目菜单栏

只在 jsx 文件中提供 新建组件 的性能

3在鼠标光标处插入组件信息

小结

此章节介绍了咱们部门以现有“智慧案场业务的微前端架构场景”(可插拔式的数据中台可能会接入若干子产品)为出发点,在此开发过程中前端组所高频应用和继续迭代的脚手架和组件库,为了让各个子产品线能疾速和低成本接入,咱们尝试在 IDE 中将他们进行了集成和实现。

目前这一套 IDE 插件撑持了咱们 15+ 个“宝宝”子产品 的我的项目初始化工作,为各个业务线同学接入后期防止了大量繁琐的配置操作;也为大家开发过程提供可扩大能力:在应用公共页面和组件时能够拿来即用,也能够疾速封装各自高频物料供所有人抉择应用;

FAW 的定位次要是 后期老同学奉献模板和组件,对新同学特地敌对,过程中新老同学一起共建,服务于整个团队。

于此同时咱们捆绑了组内都在应用的其余提效插件供大家一键装置,防止新同学和组外在开发过程体现不统一的问题。

常见插件实现原理

上面简略介绍几个 FAW 中捆绑的插件的外围实现原理。

JSSnippet

作用:实现 JavaScript/React/TypeScript 代码主动补全

仓库:VS Code ES7+ React/Redux/React-Native/JS snippets

外围实现:

// package.json
{
  "contributes": {
    "snippets": [
      {
        "language": "javascript",
        "path": "./snippets/snippets.code-snippets"
      }
    ]
  }
}
// ./snippets/snippets.code-snippets.json
{
  "typescriptReactFunctionalComponent": {
    "key": "typescriptReactFunctionalComponent",
    "prefix": "tsrfc",
    "body": [
      "import React from'react'","",
      "type Props = {}",
      "","export default function ${1:${TM_FILENAME_BASE}}({}: Props) {","  return (","    <div>${1:first}</div>","  )","}"],"description":"Creates a React Functional Component with ES7 module system and TypeScript interface","scope":"typescript,typescriptreact,javascript,javascriptreact"
  },
}

WordCount

作用:实时计算 .md 文件中字数

仓库:https://github.com/microsoft/vscode-wordcount

外围实现:

import {window} from 'vscode'

const statusBarItem = window.createStatusBarItem(StatusBarAlignment.Left);
let doc = window.activeTextEditor.document;

// 只解决 `.md` 文件
if (doc.languageId === 'markdown') {let docContent = doc.getText();
  // 将边界的空格删掉
  docContent = docContent.replace(/(< ([^>]+)<)/g, '').replace(/\s+/g,' ');
  docContent = docContent.replace(/^\s\s*/, '').replace(/\s\s*$/,'');
  let wordCount = 0;
  if (docContent !== '') {
      // 获取单词数
      wordCount = docContent.split(' ').length;
  }    
  // 将以后文件的字数在左下角状态栏展现,其中 `$(pencil)` 是 vscode 提供的图标
  statusBarItem.text = `$(pencil) ${wordCount} Words`;
  // 在状态栏展现单词数
  statusBarItem.show();}

TODOTree

作用:实现特定文本高亮

地址:https://github.com/Gruntfuggly/todo-tree

外围代码:

// 下方为伪代码
const documentHighlights = {}
const tag = 'todo'
// 1、应用正则全局匹配 todo、fixme、hack... 的坐标地位
// const regex = (//|#|<!--|;|/\\*|^|^[ \\t]*(-|\\d+.))\\s*($TAGS)/
while(( match = regex.exec( editor.document.getText() ) ) !== null ) {const range = new vscode.Range( startPos, endPos)
  const decorationOptions = {
    range,
    backgroundColor: 'green',
    color: '#fff'
  }
  // 2、通过 createTextEditorDecorationType 构建文本装璜类型对象
  documentHighlights[tag] = vscode.window.createTextEditorDecorationType(decorationOptions)
}
// 3、在编辑器中设置文本装璜定义
editor.setDecorations(decoration, documentHighlights[ tag] )
// 4、`TODO` 文本高亮展现
// TODO

// 5、还能够扩大到色号字符处展现对应色值

Vetur

作用:实现 .vue 文件的词法高亮、代码补全、错误诊断、格式化

仓库:https://github.com/vuejs/vetur

LSP 文档:https://www.bookstack.cn/read/VS-Code-Extension-Doc-ZH/docs-l…

总结

上述外围代码寄存在 https://github.com/careteenL/faw

咱们首先理解了 vscode 提供哪些能力,咱们能做什么。

再通过官网脚手架初始化一个我的项目去入门,因为 vscode 基于 electron,基于 chrome,咱们能在 vscode 中集成 webview 去丰盛页面。

然而因为在 webview 中不能调用接口,所以须要在 vscode 端进行接口调用,所以须要 vscode 和 webview 通信。

国际化的配置思路都相似。

而后基于公司外部的现状:咱们冀望有一个 GUI 去实现创立我的项目和新增页面组件。去二次开发一款 vscode 插件。

架构设计时依据性能将插件拆分,提供一个主入口,装置时主动装置相干插件。主入口还能够捆绑其余组内高频应用的插件。

而后将页面交互都交由 webview 去做,外围逻辑(调接口、渲染我的项目、新建文件)还是交由 vscode 做;并采纳 lerna 将专用逻辑进行封装,不便各个插件调用;数据局部存储在公司外部 gitlab 和公有 npm,而后采纳配置平台治理数据大 json。

新建我的项目时和脚手架 @focus/cli 的逻辑基本一致,区别在于对读取提供的 ask-for-vscode.js 文件内容时采纳 fs.readFile + new Function(code) 的形式进行 hack。

新建页面时须要保护一套组件库,并存放在公有 npm 中,而后依据用户抉择去下载对应组件的 tgz 压缩包,而后进行解析,再拷贝到以后我的项目的 pages/components 目录下,最初还需在 routes.ts 文件中插入一条路由。

在代码指定地位新增组件时,和新建页面思路相似,区别在于须要获取以后鼠标的光标地位。

工欲善其事,必先利其器。咱们能够在 IDE 中去集成组内的基建,能让开发同学更直观的理解和应用;并将重复性的工作形象封装进 VSCode 插件,撑持咱们 15+ 个“宝宝”子产品 的我的项目接入和开发,为大家开发提效。

援用

  • VSCode 官网
  • VSCode 插件开发全攻略配套 demo
  • 前端工程化 - 打造企业通用脚手架
  • 基于 VSCode 插件的前端研发工具 AppWorks
退出移动版