theia的第一个拓展-Hello World
前言
本篇文章是本人对theia中Hello World的理解,其实更像是导读,分为工作前提、创建项目、项目导读、工作区四个部分辅助阅读(保姆级别)。
工作前提
如果不喜欢看我墨迹,可以查看官方文档提供的工作前提 ,这也是最好的解决办法。
- 需要安装
theia
- 需要安装
nodejs
环境(当前是 v16.15.1) - 需要安装
node-gyp
环境(当前是v9.1.0) - 需要安装
Python3.6
或者其以上的版本 - 需要安装
visual studio
并且安装 使用C++的桌面开发 一项 - 需要安装
yarn
因为在官方中说明,yarn允许将 monorepos(包含多个npm包的存储库)构建到工作区中 - 需要安装 theia 插件开发的脚手架,
npm install -g yo generator-theia-extension
- (额外补充说明):官方推荐 使用
scoop
作为包管理工具,并且如果有多个node版本的话 推荐使用nvm
进行管理
开始构建
注意!本次的所有操作,上面的工作前提一定要做好,并且都应该把vpn关闭掉,因为会涉及安装失败问题,如果察觉到存在VPN,那么就会存在安装失败的问题!并且注意保证目录文件格式规范,例如:路径不能是中文、不能有间隔等,否则webpack在构建时会出问题
- 使用
yo theia-extension
启动项目,选择Hello World
作为模板进行项目的初始化搭建。
- 项目创建成功会在命令行中显示四个
success
提示
hello-world文件夹
在这个文件中,书写我们需要拓展帮我们实现的代码,打开 /src/browser
,可以看到有两个分别以指令名-contribution.ts
和指令名-frontend-module.ts
文件(本篇文章的指令名是hello-world
),进入文件中去,如果没有IOC-控制反转
和ID-依赖注入
的思想的话,这代码可能就读起来有点吃力了,因为这并不是很存粹的TS代码,theia使用了inversifyJS这一个框架来实现依赖注入,如果你没有这方面的很强烈推荐阅读,并且读懂官方提供的示例。
hello-world-contribution.ts文件
我试着解读这里面的代码。这个hello-world
的demo,只用到了inversifyJS
中的injectable
和inject
、ContainerModule
这三个API,其实extension的实现无非就是实现-注册-暴露这三步骤,这个文件中做的就是实现以及暴露,因为就只是简单的hellowrld代码,所以并没有把实现的代码封装出去。
@injectable()
@injectable
装饰器的作用是,当我们的定义的接口被实现成类时,那么就可以使用@injectable()
进行注释,简单理解就是会被inversifyJS
收集起来,我们不需要知道inversifyJS
底层是怎么实现的,只需要知道,每当我们需要获取时,就会返回这个函数的实例对象。
@inject()
当一个类依赖于一个接口/类时(因为在TS中定义了类其实也会隐式创建对应的接口),我们需要使用@inject
装饰器来定义一个在运行时可用的接口标识符,在本篇的hello world
中,这个标识不是inversifyJS
给的只是一个Symbol
值那么简单,它注入的是一个实例对象。我们依旧不知道inversifyJS
底层是怎么实现的,也不需要关心它什么时候帮我们new
的对象。
因为只是一个Hello World的简单例子,所以代码解读就是创建一个HelloWorld.command
的指令,并且在HelloWorldCommandContribute
注册指令,在用户点击Edit
菜单后,会显示出一个Say Hello
的一项,用户点击时就会执行this.messageService.info('Hello World!')
这段代码。
hello-world-frontend-module.ts文件
这个文件的主要使用的类就是ContainerModule
,ContainerModule这个类,其实是方便我们把业务分成各个模块进行导出的,如果开发的项目比较大时,可以是用这个方法进行有效管理,因为如果全部的绑定都在Contaniner中进行绑定时,就会显得十分臃肿。
ContainerModule
这个类中只有一个参数就是回调函数,回调函数中却又若干个形参,这里主要使用的就是bind
参数,bind
回调函数会根据传入的标识符生成一个被绑定的对象,这个对象会被放进到ContainerModule
中。to
回调函数会接受一个类,进而进行绑定。可以抽象理解为以下,仅供入门参考,但是事实上它实现起来与WeakMap
更相似。
containers: {
hello-world-frontend-module: {
// 指令
CommandContribution: {
HelloWorldCommandContribution: {
registerCommands(...): void ...
},
... // 如果有更多
},
// 菜单
MenuContribution: {
HelloWorldMenuContribution: {
registerMenus(...): void ...
},
... // 如果有更多
}
},
other-frontend-module: {
...
},
...
}
那么当执行代码后,theia
就会根据你暴露的绑定,执行相关的命令,在这个例子中可以简单分解成两部分理解,用户点击Edit
按钮列表中,系统会增加一个选项,叫做Say Hello
,这一步相当于系统执行了MenuContribution
中的HelloWorldMenuContribution
类中的代码,然后点击Say Hello
按钮,那么就会在右下角弹出一个信息窗口,显示Hello World,因为HelloWorldMenuContribution
依赖了HelloWorldCommandContribution
中注册的指令,所以也会它会去找CommandContribution
对应的HelloWorldCommandContribution
实例。
工作区
其实上面在根目录的package.json
中简单的提及过,一个拓展的工作区有三个,那么该执行哪一个才能看到效果?区别又是什么?
hello-world工作区
在这个工作区中,是留给程序员编写代码的,然后暴露出相关的命令给theia
执行,里面的package.json
并没有script
可以启动的命令.
...
"scripts": {
"prepare": "yarn run clean && yarn run build",
"clean": "rimraf lib",
"build": "tsc",
"watch": "tsc -w"
},
...
browser-app工作区
这个工作区就有意思了,它最终运行后,结果是显示在浏览器上的。多说无益,直接上代码和图片才是真理。
- 第一步打开项目,进入
browser-app
文件下cd ./browser-app
,打开终端输入yarn start browser-app
后执行,打开任意浏览器,输入localhost:3000
,忽略~你就会得到下面的页面
- 点击左上角的
Edit
,选择Say Hello
,注意观察右下角弹窗显示。
electron-app工作区
其实第二种工作区的方式,在开发中好像并不是很常见,因为大部分人都喜欢在编辑器本身进行查看效果。
- 回到根目录下,在命令行中输入
yarn rebuild:electron
,然后等待一段时间后就会生成一个.browser_modules
文件夹,但是现阶段没必要管,因为我们的操作并不是在这个文件夹中进行
补充
上面那几个基本的操作就能满足我们的需求了吗,其实不然,如果我们修改了hello-world
的代码,那么我们要怎么运行?貌似也没有介绍的样子?
- 其实很简单,比如我们在
hello-world-contribution
文件中修改我们的弹窗显示内容
-
其实有过前端开发经验的已经看出来了,在
hello-world
中的package.json
其实有一个script
中的--prepare
命令,这个指令可以直接让项目更新。在命令行中写入yarn prepare
-
再进入
electron-app
文件夹终端中输入yarn prepare
后再执行yarn start electron-app
,再根据上面的执行操作,得到下面的结果。
总结
本篇是基于Hell world
入门的引导文章,没有深入的讨论每个API的使用,只是浅谈该怎么运行和看懂代码。
参考
thiea官方文档:theia-ide.org/docs inversifyJS官方文档:github.com/inversify/I…
转载自:https://juejin.cn/post/7127923816897970207