基于Jenkins、Figma插件实现原理探究web系统插件化架构


背景:对于大型web应用而言,功能极其丰富复杂,为了具备扩展性,部分项目选择插件化架构方式,开放一部分系统Hook给具备开发能力的用户,不但提升用户的体验感,还同时丰富平台功能,一举两得。如何构建具备插件化能力的平台?本文尝试通过分析jenkins jar包插件实现方式及Figma前端插件实现方式探究插件化架构方案。

我们常见的支持插件化的应用是一些桌面端编辑器,如VSCode,Eclipse,Idea,Sublime等,也有支持动态扩展的web应用,如构建工具Jenkins,支持前端插件扩展的web应用,如设计工具Figma。不管哪种应用方式,基本的设计逻辑大致如下。

我们当前主要研究的是web系统的插件化构架方案,本地插件化软件先不讨论。主要以jenkins和figma的两种实现方式进行探讨。

Jenkins插件化系统

Jenkins可以支持git, svn, maven等很多功能,这些都是Jenkins的插件,Jenkins通过扩展点及前端视图模板来提供插件扩展能力,以jar包的方式上传到指定目录,创建类加载器 class-loader,使用插件策略PluginStrategy加载可以激活的插件。

(一)扩展点

Jenkins有很多的扩展点ExtensitonPoint),它是Jenkins系统的某个方面的接口或抽象类。这些接口定义了需要实现的方法,而Jenkins插件需要实现这些方法,也可以叫做在此扩展点之上进行扩展Jenkins。有关扩展点的详细信息,请参阅Jenkins 官方ExtentionPoints文档。通过这些扩展点我们可以写插件来实现自己的需求。
下面是一些常用的扩展点:

  • Scm :代表源码管理的一个步骤,如下面的Git,Subversion就是扩展的Scm

  • Builder : 代表构建的一个步骤,如下图中在构建过程中,我们可以增加一个构建步骤,而每一个选项都是对应一个Builder,在每一个Builder中都有自己不同的功能。如Execute shell,这就是一个ShellBuilder,意味着在构建过程中会执行一个shell命令

  • Trigger:代表一个构建的触发,当满足一个什么样的条件时触发这个项目开始构建。比较常用的触发就是当代码变更时触发,如果我们需要实现一些比较复杂的触发逻辑,就需要扩展Trigger这个扩展点

  • Publisher:Publisher代表一个项目构建完成后需要执行的步骤,如选项中的E-Mail Notifaction就是一个Publisher插件,选择这个选项后,当项目构建完成,就会使用email来通知用户,假如想要在项目构建完成后将构建目标产物发送到服务器上,则可以扩展此扩展点。

(二)Jenkins中的视图

Jenkins 使用jelly来编写视图,Jelly 是一种基于 Java 技术和 XML 的脚本编制和处理引擎。Jelly 的特点是有许多基于 JSTL (JSP 标准标记库,JSP Standard Tag Library)、Ant、Velocity 及其它众多工具的可执行标记。Jelly 还支持 Jexl(Java 表达式语言,Java Expression Language),Jexl 是 JSTL 表达式语言的扩展版本。Jenkins的界面绘制就是通过Jelly实现的。

另外一个开源的插件化后台管理系统:grape: 前后端可插件开发的后台管理系统 (gitee.com)

Figma前端插件系统

Figma 是一个在线协作式 UI 设计工具,具有插件扩展功能,只要有前端开发能力的用户均可开发自己的插件来扩展设计体验。

Figma的插件是纯前端的插件方式,没有后端代码,它的插件系统是如何工作的?

这是一个基于 TypeScript + React 技术栈,使用 Webpack 构建的 Figma 插件目录结构如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
├── README.md
├── figma.d.ts
├── manifest.json
├── package-lock.json
├── package.json
├── src
│ ├── code.ts
│ ├── logo.svg
│ ├── ui.css
│ ├── ui.html
│ └── ui.tsx
├── tsconfig.json
└── webpack.config.js

在其 manifest.json 文件中包含了一些简单的信息。

1
2
3
4
5
6
7
{  
"name": "React Sample",
"id": "738168449509241862",
"api": "1.0.0",
"main": "dist/code.js",
"ui": "dist/ui.html"
}

可以看出 Figma 将插件入口分为了 mainui 两部分, main 中包含了插件实际运行时的逻辑,而 ui 则是一个插件的 HTML 片段。即 UI 与逻辑分离。 main 中的 js 文件被包裹在一个 iframe 里加载到页面上。而 ui 中的 HTML 最终也被包裹在一个 iframe 里渲染出来,这将有效的避免插件 UI 层 CSS 代码导致全局样式污染。

ui展示是通过如下代码加载,会弹出个DIV,展示manifest.josn中指定的ui地址内容:

1
figma.showUI(__html__);

在上一层使用 window.addEventListener进行监控,事件通信使用 parent.postMessage,发送事件及数据。figma使用了两层iframe来嵌套装载插件内容。

我画了架构图来描述,大致如下:

开发的插件可在本地app中进行调试,最终发布到服务器。

总结

插件系统在设计时要考虑的基本内容,如何开放数据接口,如何加载插件,何时何地启动插件,插件如何与主程序通信问题,如何保证插件安全性?前端插件化使用iframe sandbox是一个通用可行的办法,但依然会有很多问题。

参考文档

How Plugins Run · Figma Developers

Figma 插件开发 101

大型 Web 应用插件化架构探索

iframe参考

window.postMessage


文章作者: KavenRan
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 KavenRan !
 上一篇
一文理清Thymeleaf前世今生 一文理清Thymeleaf前世今生
什么是Thymeleaf Thymeleaf 官网是这么解释的:Thymeleaf is a modern server-side Java template engine for both web and standalone envi
2021-06-15
下一篇 
没有找准原理,怎么可能想出好的创业想法 没有找准原理,怎么可能想出好的创业想法
谁在开始创业的时候,都想着自己做的事是一定可以成功!否则,谁会去做呢?可为什么那么多创业公司不成功呢? [TOC] 在日常工作中,我们经常会遇到一些想要创业的朋友表达自己很想出来做点事情,但就是不知道做什么好。表面上看起来,现在能想到
2021-05-31
  目录