上一篇:使用Theia——創建擴展包
創建Theia插件
下面我們來看看如何創建Theia插件。作為示例,我們將注冊一個Hello World命令,該命令顯示一個“Hello World”通知。本文將指導你完成所有必要的步驟。
Theia的架構
插件與擴展包
Theia是一個可擴展的IDE。你可能聽說過擴展是定制IDE的一種方式,而插件則是一種可以被添加到Theia中的新的可擴展模型。下面是一些有關插件和擴展包之間的主要區別。
插件
優點:
-
代碼隔離:插件的代碼運行在獨立的進程中,它不會阻塞Theia核心進程。
-
可以在運行時加載。不需要重新編譯整個Theia IDE。
-
減少編譯時間。
-
自包含。插件可以被打包成一個獨立的文件,並在稍后直接加載。它不需要從npmjs或者其它的地方獲取額外的依賴項。
-
簡單的API
-
不需要學習inversify或任何其它的框架。
-
單個入口,帶有代碼補全,以查看可能的與JsDoc相關的調用。
-
由於API是向后兼容的,所以很方便從一個Theia版本升級到另一個版本。
缺點:
- 需要遵守預定義的API。如果沒有通過API提供contribution point,則不可能對功能進行調整。注意當前的API可以進行擴展以支持更多的功能。
設計
Theia應用程序由一個核心組成,它為特定功能提供一組小部件、命令和處理程序等。
Theia定義了一個運行時的API,它允許插件定制IDE並將它們的功能添加到Theia應用程序的各個地方。
在Theia中,插件可以通過一個名為theia的對象訪問API,該對象在所有的插件中都可用。有關API的更多細節可以查看
這里。
插件有兩種性質:
-
后端插件。后端插件與VS Code的插件很像。插件的代碼運行在服務端自己獨立的進程中。當API被調用時,它會在用戶的瀏覽器或UI上發送一些actions來注冊新命令,等等。所有的回調都在服務端專有的進程中運行。
-
前端插件。這種情況下所有的回調都在瀏覽器或UI的工作線程中運行。這些插件只被授權使用“瀏覽器兼容”模塊。例如,不允許讀寫文件,因為所有的插件都運行在瀏覽器端。但是,如果你確實希望在客戶端避免某些網絡操作,那么這種方法是有用的。
必要條件
這里有一個運行的Theia實例,(v0.3.12+)可以從Theia倉庫獲得Theia的說明。
項目結構
我們創建了一個名為
theia-hello-world-plugin的新目錄,用來存放我們項目的源代碼。
這個新目錄可以創建在任何路徑下,它是獨立於Theia源代碼的。
為了簡化倉庫的設置,你可以使用
Yeoman代碼生成器來幫助快速生成項目的腳手架。
可以通過下面的命令來安裝和運行生成器。注意,你可以在運行Theia實例的新終端中輸入這些命令。
npm install -g yo @theia/generator-plugin mkdir theia-hello-world-plugin cd theia-hello-world-plugin yo @theia/plugin
在上面的命令中:
-
npm install -g yo @theia/generator-plugin命令在全局安裝Theia生成器。
-
yo @theia/plugin命令調用yeoman生成器來創建Theia插件生成器的模板。
下面是生成器運行的動態圖。
每個問題使用默認選項即可。
在這一步中,
theia-hello-world-plugin目錄中已經有了一個從源碼構建的插件了。
實現插件
我們來看下自動生成的代碼。
{ "name": "theia-hello-world-plugin", "publisher": "theia", "keywords": [ "theia-plugin" ], "version": "0.0.1", "files": [ "src" ], "devDependencies": { "@theia/plugin": "latest", <-- 1. Theia API dependency "rimraf": "^2.6.2", "typescript": "^2.9.2" }, "scripts": { "prepare": "yarn run clean && yarn run build", "clean": "rimraf lib", "build": "tsc" }, "engines": { "theiaPlugin": "latest" <-- 2. this plug-in requires Theia runtime }, "theiaPlugin": { "backend": "lib/theia-hello-world-plugin-backend-plugin.js" 3. <-- entrypoint } }
在這個package.json文件中,有三個重要的部分:
-
首先,在 devDependencies中,有一個依賴項 @theia/plugin,這個包將在插件的代碼中調用Theia API(如添加新命令和顯示消息)。
-
第二, engines部分包含 theiaPlugin,它允許將node包標記為可在特定版本的Theia上運行。
-
第三, theiaPlugin部分包含插件的入口位置。對於后端插件, backend的值是指向插件的javascript的路徑。
我們來看下生成的單個源代碼文件的內容。下面這個文件的路徑是
src/theia-hello-world-plugin-backend-plugin.ts,它包含TypeScript代碼。
import * as theia from '@theia/plugin'; export function start() { const informationMessageTestCommand = { id: 'hello-world-example-generated', label: "Hello World" }; theia.commands.registerCommand(informationMessageTestCommand, (...args: any[]) => { theia.window.showInformationMessage('Hello World!'); }); } export function stop() { }
可以看到,只需幾行代碼就可以注冊一個命令並顯示通知消息。
第一行很重要,用來導入API。
import * as theia from '@theia/plugin';將所有的Theia插件的API導入到一個theia對象中。
代碼中包含兩個方法,
start()和
stop()。
方法
start()在插件被加載時調用。在這個方法中,有一個action,用來注冊hello world命令和一個回調,以及顯示
hello world的消息。Command對象有一個
id和一個用來在命令面板中顯示的
label。
方法
stop()的內容為空,它在插件停止時被調用,用於執行某些操作。此方法是可選的,如果為空則可以將其刪除。
運行插件
現在我們來看看這個插件的運行情況。在Theia中有一種被稱之為
hosted mode的模式,該模式允許我們在其中一個Theia實例中開發插件,並將其部署到另一個Theia實例中。這樣就可以很方便地生成插件並進行測試。
首先,確保已經打開Theia中生成插件的目錄(它必須是你workspace的一部分)。然后打開命令面板(F1鍵),搜索
Hosted mode: start instance,選擇該命令。

瀏覽workspace並選擇插件的目錄(其中包含
package.json文件)。

這將在
3030端口上啟一個新的Theia實例。你會看到打開了一個新的選項卡(可能你需要驗證一下),有一個新的實例在
Development Host下運行(可以在狀態欄中看到)。
在
Development Host實例中,打開命令面板(F1鍵)然后搜索
Hello World命令。

選擇該命令,你將在屏幕上看到
Hello World的消息。
開發插件
正如上面所說的,Theia API由TypeScript提供,同時在開發過程中還支持代碼補全功能和JsDoc。
更新插件
假如你想將消息的內容從
Hello World改成
Hello Theia,可以進到
Hosted Plugin: running實例中(看狀態欄上的顯示),編輯TypeScript文件
src/theia-hello-world-plugin-backend-plugin.ts,將
theia.window.showInformationMessage('Hello World!');改成
theia.window.showInformationMessage('Hello Theia!');
在插件的根目錄下運行命令
yarn build,重新編譯源代碼。然后你只需要刷新
Development Host的實例,插件就會被重新加載。
注意:你也可以使用watch模式來代替手動刷新。
插件的API
VS Code代碼實現
Theia 提供VS Code API,可以查看這個鏈接的內容以獲取當前的狀態,
比較Theia和VS Vode API。