上一篇:Theia——云端和桌面版的IDE
架構概述
本節描述了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)
擴展包
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系結的,
這使得任何人都可以系結ConnectionHandler,現在,當messageingModule啟動時,所有的ConnectionHandlers都將被初始化, 原文地址:https://theia-ide.org/docs/architecture轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/6678.html
標籤:其他
下一篇:使用Theia——添加語言支持
