Theia架构

上一篇:Theia——云端和桌面版的IDEhtml

架构概述

  本节描述了Theia的总体架构。
  Theia被设计为一个能够在本地运行的桌面应用程序,也能够在浏览器和远程服务器之间工做。为了支持这两种工做方式,Theia运行在两个独立的进程中,它们被称之为前端和后端,相互之间经过WebSockets上的JSON-RPC消息或HTTP上的REST APIs来通讯。对于Electron而言,前端和后端都在本地运行,而在远程上下文中,后端运行在远程服务器上。
  前端和后端进行都有它们各自的依赖注入(DI)容器(详见下文),以方便开发者进行扩展。

前端

  前端部分负责客户端的UI呈现。在浏览器中,它只是简单地在渲染循环中运行。而在Electron中,它运行在Electron窗口中,这是一个包含Electron和Node.js APIs的浏览器窗口。所以,任何前端代码均可以把浏览器而不是Node.js做为一个运行平台。
  启动前端进程将首先加载全部扩展包的DI模块,而后获取一个 FrontendApplication的实例并在上面调用 start()

后端

  后端进程运行在Node.js上。咱们使用express做为HTTP服务器,它能够不使用任何须要浏览器平台的代码(DOM API)。
  启动后端应用程序将首先加载全部扩展包的DI模块,而后获取一个 BackendApplication的实例并在上面调用 start(portNumber)
  默认状况下后端的express服务器也为前端提供代码。

按平台进行区分

  在扩展包的根目录下,包含以下子目录层级,按不一样的平台进行区分:
  • common目录下包含的代码不依赖于任何运行时。
  • browser目录下包含的代码须要运行在现代浏览器平台上(DOM API)。
  • electron-browser目录下包含了须要DOM API及Electron渲染进程特定的APIs的前端代码。
  • node目录包含了须要运行在Node.js下的后端代码。
  • node-electron目录包含了Electron特定的后端代码。

参见

  能够查看这篇文章了解有关Theia架构的简要概述:前端

  利用JS实现多语言IDE——目标和架构(Multi_Language IDE Implemented in JS - Scope and Architecture)node

扩展包

  Theia由扩展包构成。一个扩展包就是一个npm包,在这个npm包中公开了用于建立DI容器的多个DI模块( ContainerModule)。
  经过在应用程序的 package.json中添加npm包的依赖项来使用扩展包。扩展包可以在运行时安装和卸载,这将触发从新编译和重启。
  经过DI模块,扩展包能提供从类型到具体实现的绑定,即提供服务和功能。

Services和Contributions

  本节咱们将描述一个扩展包如何使用另外一个扩展包中的服务,以及它们如何给Theia提供功能。

依赖注入(DI)

  Theia使用DI框架 Inversify.js来链接不一样的组件。
  DI在建立时注入组件(做为构造函数的参数),从而将组件从依赖项中完全解耦出来。DI容器根据你在启动时经过所谓的容器模块提供的配置项来进行建立。
  例如, Navigator小部件须要访问 FileSystem用来在树形结构中显示文件夹和文件,可是 FileSystem接口的实现对 Navigator来讲并不重要,它能够大胆地假设与 FileSystem接口一致的对象已经准备好并可使用了。在Theia中, FileSystem的实现仅仅是一个发送JSON-RPC消息到后端的代理,它须要一个特殊的配置和处理程序。Navigator不须要关心这些细节,由于它将获取一个被注入的 FileSystem的实例。
  此外,这种结构的解耦和使用,容许扩展包在须要时能提供很是具体的功能实现,例如这里提到的 FileSystem,而不须要接触到 FileSystem接口的任何实现。
  DI在Theia中是一个很是重要的部分,所以,咱们强烈建议先学习 Inversify.js的基础知识。

Services

  Service只是一个提供给其它组件使用的绑定。例如,一个扩展包能够公开 SelectionService,这样其它扩展包就能够得到一个注入的实例并使用它。

Contribution-Points

  若是一个扩展包想要提供一个钩子,由其它扩展包来实现其中的功能,那么它应该定义一个 contribution-point。一个 contribution-point就是一个能够被其它扩展包实现的接口。扩展包能够在须要时将它委托给其它部分。
  例如, OpenerService定义了一个contribution point,容许其它扩展包注册 OpenHandler。你能够查看 这里的代码。
  Theia已经提供了大量的contribution points列表,查看已存在的contribution points的一个好方法是查找 bindContributionProvider的引用。

Contribution Providers

  一个contribution provider基本上是contributions的容器,其中的contributions是绑定类型的实例。
  这是很是通用的。
  要将类型绑定到contribution provider,你能够这样作:
(来自messageing-module.ts)
export const messagingModule = new ContainerModule(bind => {
    bind<BackendApplicationContribution>(BackendApplicationContribution).to(MessagingContribution);
    bindContributionProvider(bind, ConnectionHandler)
});
  最后一行将一个ContributionProvider绑定到一个包含全部ConnectionHandler绑定实例的对象上。
  像这样来使用:
(来自messageing-module.ts)
constructor( @inject(ContributionProvider) @named(ConnectionHandler) protected readonly handlers: ContributionProvider<ConnectionHandler>) {
    }

  这里咱们注入了一个ContributionProvider,它的name值是ConnectionHandler,这个值以前是由bindContributionProvider绑定的。git

  这使得任何人均可以绑定ConnectionHandler,如今,当messageingModule启动时,全部的ConnectionHandlers都将被初始化。
 
相关文章
相关标签/搜索