插件化
大家在进行前端开发过程中,可能都会养成一个习惯,当我们面对某一个特定问题,需求解决方案的时候,都会在社区中找好用的插件。如果能够找到匹配的插件,原本两天的工作量,可能半个小时就搞定了。
不管是以前撑起前端大半江山的JQuery,还是现在提升前端开发体验的构建工具例如Webpack,都采用了插件架构。
插件架构
插件架构宏观上来讲就是一种框架能够在确定的点上执行外部的代码,而不需要提前知道这部分代码的细节。
它既可以很简单,也可以很复杂。我们可以编写webpack插件,也可以开发vscode的插件,其基本架构是相似的。
开发插件需要遵循一些约定,就像网络传输需要协议。它们必须能够被主进程以某种方式获取并使用。通常最初的开发者会发布一些接口或开发套件,允许其他的开发者对原系统开发插件,提供新的能力。
插件架构师开放封闭原则(OCP)的一种开发原则的体现,表明系统对拓展开放,对修改封闭。插件架构解决了不需要修改核心系统代码而可以对系统增加一些额外的功能特性,只需要一些额外的代码。插件可以单独开发,单独测试。
插件三要素
- pluginCore:插件内核,提供插件运行时,管理插件的加载、运行、卸载等生命周期(类比浏览器)
- pluginAPI:插件运行时需要的基础接口(类比浏览器例子,相当于window)
- plugin:一系列特定功能的独立模块(类比浏览器例子,相当于不同的网页)
插件核心
插件体系主要分为插件管理、插件连接、插件通信。插件管理中核心系统需要知道哪些插件可以用,注册到哪里,注册顺序等。插件连接是插件的实现规范以及与核心系统的连接规范。插件通信是核心系统提供插件的通讯机制。
插件架构的好处
插件机制可以保证在系统提供的能力范围内参与系统内部定制化的改造,这为第三方开发提供了更便利的条件,而且这种机制的存在可以激发更多的想法,促进整个生态的发展。采用插件机制有开放生态、拓展性强、无入侵定制化、规则指定等好处。
插件与组件与库的区别?
组件是调用者只需关注输入和输出,总思想就是分而治之、重复利用、低耦合。组件解决资源整合问题、增强功能促进开发效率,提高可维护性,便于协同开发。
插件是参与程序内部运行环节的一段或多段代码集合。即plugin遵循一定规范写出来方便程序展示效果,拥有特定功能且方便调用。
库是为解决某些特定需求的程序功能集合。即library,如JQuery,常用于方便dom操作、解决浏览器兼容等问题。
微内核架构思想
插件架构也称为微内核架构,部分复杂项目在不使用微内核设计时,功能过于耦合,不利于拓展和维护。
TIP
微内核架构模式,是软件开发领域非常常见的一种架构模式,非常利于构建松耦合,高扩展的系统。
微内核架构模式的核心是调度器,微内核架构本身不会关注实际业务模块,具体业务模块会通过定义注册插件的方式,从而扩展整个程序的能力。
由此可以看出基于微内核架构模式设计的系统是非常容易扩展的,同时每个插件相互独立,从而使得系统耦合性低,有利于维护。
如何开发一个插件调度器?
思考调度器的核心功能
- 注册插件功能
- 执行插件
- 维护整个生命周期的执行上下文
思考好的插件设计,迎合调度器
- 适当抽象
- 简洁API设计
- 插件本身的性能优化
应用场景
微内核设计广泛应用于以下场景:
- 对拓展性要求非常高(例如编辑器,vscode也是非常棒的案例)
- 程序本身不关心业务实现(例如前端微服务架构基座实现)
- 开放的程序开发维护权限(任何开发者在看完插件文档后都可以为比较轻松为程序增加新功能)
优劣势
优势
- 拓展性高
- 本身不关心业务实现
- 将业务实现权限移交给开发者
劣势:前面提到微内核设计的核心是插件调度器,所以调度器的性能决定了基于微内核设计的程序性能,往往会使程序性能低下。
性能主要是花费在遍历插件上
插件生命周期及通信管理
插件化系统设计核心在于插件调度器,主要使用设计模式包含:策略模式、职责链模式。
调度器内核我们称为Kernel,插件记作Plugin
插件系统设计就是针对Kernel与Plugin的设计
Kernel需要具备的:
- 系统基础配置(例如一些环境变量相关参数等)(isHmr、isProduction...)
- 插件池(plugins) Map
- 生命周期钩子(hooks) Map
插件生命周期
生命周期亦称钩子(Hook),用于在系统陈旭运行阶段触发对应事件调用,以过往React为例,一个组件的生命周期包含:
- onComponentWillMount
- onComponentDidMount
- onComponentDidCatch
- ...
怎样设计生命周期?插件生命周期设计需要遵循以下原则:
- 捋清微内核系统运行逻辑
- 特殊节点安插检视点(钩子)
- 尽可能少且覆盖大部分场景
插件通信及交互状态管理
插件之间通信需要传信人(执行上下文)
插件调度器从创建到销毁总是维护当前执行的程序执行的上下文,该执行上下文通俗来说可以理解为一个参数对象,存储了执行插件沿途所收集的环境变化。
以Koa框架为例,ctx上始终维护执行过程中所做的请求、响应更改。