🛠️搭建项目开发工具IDE——Chapter 2 详细分析VSC
导语:VSCode作为微软推出的编辑器,在这几年逐渐被越来越多的人接受。轻便、好用、易扩展是他最重要的三个特点,其运行速度较同为 Electron 架构的Atom要快许多。微软也将代码开源放在GitHub上,一起来揭开vscode的神秘面纱吧。
- 此文开始于2019-07-30 晚上12:43:35,参考的Vscode源码版本为 1.19.3 VSCode v1.19.3,可直接下载ZIP压缩包,源码总大小11.7M。
- VSCode开源代码的Github地址为:
https://github.com/microsoft/vscode
项目阶段(持续更新)
- [ ] 第一阶段2019.07.28——介绍如何开发VSCode插件
- [ ] 第二阶段2019.08.09——详细分析VSCode开源代码 Part 1 代码结构
- [ ] 第三阶段2019.08.xx——详细分析VSCode开源代码 Part 2 源码编译运行
一、项目架构背景介绍
Electron
- Electron 是基于 Node.js 和 Chromium 的跨平台桌面应用开发框架。使用 JavaScipt,HTML,CSS 真正将 Node.js 带到了前端。Electron 通过 BrowserWindow 可以创建一个本地窗口,并加载一个HTML文档,BrowserWindow中的内容就是一个浏览器窗口,不仅能创建DOM元素,同时能使用任意的Node模块,并且还可以通过IPC与主进程通讯。
多进程
-
每一个 Electron 应用都对应一个主进程(main process), 主进程通过BrowserWindow创建的每个本地窗口对应一个渲染进程(renderer process)。
vscode-process.png
主进程
- vscode的主进程主要负责创建窗口和菜单,生命周期管理,为进程通信基站(IPC Server),自动更新,工具条菜单栏注册等与系统相关的功能。
渲染进程
- 绝大多数代码都是运行在渲染进程中的,渲染进程负责界面的显示,响应用户操作。前面说到在浏览器中也可以使用Node模块,渲染进程还通过Node创建了一个插件子进程,负责插件的初始化。另外渲染进程还可以创建Worker执行一些复杂的计算,比如markdown的解析;需要跨renderer共享的用子进程拆出去,交由main管理。
插件进程
- 每一个渲染进程同时也对应一个插件进程,插件运行在单独的进程不会对渲染进程造成影响,这也是vscode比atom要快的原因。Atom中插件是直接运行在渲染进程中的,所以当插件很多的时候会卡。同时又由于vscode的插件运行在一个普通的Node进程中,所以对UI的操作能力是比较弱的,这点不及Atom。
二、源码分析基本结构
将GitHub托管的vscode源码clone下来,此处介绍的版本号为 1.19.3 VSCode v1.19.3。
目录结构
- 只展示主要的文件及目录
├── build # gulp编译构建脚本
├── extensions # 内置插件
├── resources # 平台相关静态资源,图标等
├── scripts # 工具脚本,开发/测试
├── src # 源码目录
├── test # 测试套件
├── out # 编译输出目录(执行编译后会有)
├── i18n # 国际化翻译包(最新版本已经移除,改用第三方插件形式下载使用)
├── package.json # 项目配置文件
├── product.json # App meta信息
└── gulpfile.js # gulp task
- src目录结果
├── bootstrap-amd.js # 子进程实际入口
├── bootstrap.js # 子进程环境初始化
├── buildfile.js # 构建config
├── cli.js # CLI入口
├── main.js # 主进程入口
├── paths.js # AppDataPath与DefaultUserDataPath
├── typings
│ └── xxx.d.ts # ts类型声明
└── vs
├── base # 通用工具/协议和UI库
│ ├── browser # 基础UI组件,DOM操作、交互事件、DnD等
│ ├── common # diff描述,markdown解析器,worker协议,各种工具函数
│ ├── node # Node工具函数
│ ├── parts # IPC协议(Electron、Node),quickopen、tree组件
│ ├── test # base单测用例
│ └── worker # Worker factory和main Worker(运行IDE Core:Monaco)
├── code # VS Code主窗体相关
├── editor # 对接IDE Core(读取编辑/交互状态),提供命令、上下文菜单、hover、snippet等支持
├── platform # 支持注入服务和平台相关基础服务(文件、剪切板、窗体、状态栏)
├── workbench # 协调editor并给viewlets提供框架,比如目录查看器、状态栏等,全局搜索,集成Git、Debug
├── buildunit.json
├── css.build.js # 用于插件构建的CSS loader
├── css.js # CSS loader
├── loader.js # AMD loader(用于异步加载AMD模块,类似于require.js)
├── nls.build.js # 用于插件构建的NLS loader
└── nls.js # NLS(National Language Support)多语言loader
与业务相关的关键部分
- src/vs/code:主窗体、工具栏菜单创建
- src/vs/editor:代码编辑器,IDE核心相关
- src/vs/workbench:UI布局,功能服务对接
src下的重要文件(夹)
base
base包封装了大量API,实现常用功能。在vscode中目录结构都是都是按照browser,common,node,electron的方式划分的。
- browser
browser中实现了一个简单的UI库,包括 Button,CheckBox,List,Scrollbar等常用组件。并且封装了一套类似JQuery的DOM操作API(参见 dom.ts 和 builder.ts)。
- common
common包中封装了大量实用工具类。如
- arrays.ts,strings.ts,objects.ts 封装了一套类似underscore的api。
- uri.ts 和 paths.ts 实现了路径解析功能。
- winjs.base.js 实现了一个功能强大的Promise。
- 另外还有很多其他的工具类,每一个模块的耦合度都很低,基本都可以单独拿出来用,学习起来也和容易。这里就不一一介绍了。
- node
node包中封装了一些node实现的功能。如
- extfs.ts 和 pfs.ts 封装了文件操作相关的api。
- request.ts 封装了网络请求的api,能方便的发送网络请求,加载json,下载文件。
- service.cp.ts 和 service.net.ts 封装了socket和进程通讯的api。
- zip.ts 封装了解压缩文件的操作
- parts
这个包额外定义了一些复杂的UI组件,tree 和 quickopen。
editor and language
本篇主要了解vscode基本框架的结构,这两包作为编辑器功能的主要实现,这里面的逻辑太复杂就不细说了。
platform and workbench
vscode中基本所有的具体功能实现代码都在这两包中。platform主要定义了一些服务的接口和简单实现,workbench则实现了这些接口,并且创建了一个工作台,构建了一个完整界面结构。
每层按目标执行环境细分组织结构(部分重要):
- common:可跨环境复用的
- browser:依赖浏览器API的,比如DOM操作
- node:依赖Node API的
- electron-browser:依赖electron renderer-process API的
- electron-main:依赖electron main-process API的
vscode-Monaco.png★ IDE Core可独立使用,Monaco可以直接生成编辑器页面。Monaco的github仓库
下一节:第三阶段——详细分析VSCode开源代码 Part 2 源码编译运行
部分图片、文字摘取自:
- vscode源码剖析:总有人要做相同的事情
- VS Code源码简析:所幸巨人的肩膀正变得越来越高