框架介绍
OpenSumi 框架旨在解决阿里经济体内部 IDE 产品研发的重复建设问题,满足 IDE 在更多垂直场景的定制能力,同时实现 Web 与本地客户端共用底层,让 IDE 研发从早期的“刀耕火种”时代向“机器化大生产”时代迈进。
如果你对 OpenSumi 框架的建设有兴趣,欢迎查看 如何贡献代码 为 OpenSumi 框架建设出一份力。
为了保证框架可以同时在
Web
和
Electron
环境下运行,OpenSumi 采用了一套前后端分离、通过一层抽象的通信层进行相互调用的项目结构。
在
Web
上,我们使用
WebSocket
来作为通信的实现。
在
Electron
上,我们则是
IPC
通信。
每一个通信的连接对应前后端一个独立的 DI (Dependence Inject) 容器,所以 OpenSumi 的后端实现是无状态的 ,不同连接之间是严格隔离的。
在 OpenSumi 内主要有三个核心进程:
为了保证插件的问题不会影响 IDE 的性能表现,插件能力上 OpenSumi 采用了跟
VS Code
类似的方案,通过独立的插件进程去启动插件,插件进程再通过后端进程与前端进程进行通信。
OpenSumi 的不同能力实现被拆分到了不同的模块内,这些模块通过 贡献点机制 (Contribution Point) 、 DI 机制 (Dependence Inject) 互相之间有较弱的依赖关系,对于一些比较核心的基础模块,如主题服务、布局服务等,也会被其他模块直接依赖。
因此,在集成开发过程中需要保证一些模块的引入顺序。
整体启动的生命周期如下图所示:
什么是模块?
模块是指
OpenSumi
中
package
目录下的一个包,它可以发布到
npm
,并通过集成时安装依赖的方式引用。
通常情况下,模块是一个独立的功能实现,例如
debug
模块基于
DAP
实现了一层通用的调试适配器,包括了调试器前端、会话管理等核心功能。并通过插件 API 的方式将其提供给插件调用。
一个模块的基本结构如下
├── __tests__ │ ├── browser │ └── node └── src │ ├── browser │ ├── common │ └── node └── webpack.config.js └── package.json └── README.md
在
OpenSumi
中,你可以通过
yarn run create [模块名]
的方式自动创建并关联引用关系。
模块即可以包含
Browser
层代码,也可以包含
Node
层代码
browser
层代码一般用于处理视图相关的能力,以 OpenSumi 中的
search
模块为例,搜索的界面就是由
browser
层进行实现。
node
层代码一般用于处理需要使用到
Node.js
能力的逻辑,例如搜索面板中的全局搜索能力就需要
node
层进行实现。
common
层一般用于存放一些公共的变量、工具方法、类型声明等。
拓展 Browser 层能力
我们通过以下的文件结构拓展
Browser
层能力,你可以通过在
providers
中声明相关内容来拓展能力,详细案例可见我们的
Todo List 案例
。
// Browser 模块入口
import { Provider, Injectable } from '@opensumi/di';
import { BrowserModule } from '@opensumi/ide-core-browser';
import { HelloWorld } from './hello-world.view';
@Injectable()
export class ModuleDemoModule extends BrowserModule {
providers: Provider[] = [];
拓展 Node 层能力
我们通过以下的文件结构拓展 Node
层能力,你可以通过在 providers
中声明相关内容来拓展能力,详细案例可见我们的 Todo List 案例。