大家好,我是Eluxjs的作者,Eluxjs是一套基于“微模块”和“模型驱动”的跨平台、跨框架『同构计划』,欢送理解...

文前申明,以下推断和论断纯属集体摸索,鉴于自己常识程度所限,舛误在劫难逃,恳请各位大佬不吝赐教...

什么是前端“微模块”?

Elux中的『微模块』是指在Web前端工程中,将代码和相干资源依照不同的业务性能进行归类和模块化。

依据业务性能进行模块化始终以来都是后端的广泛做法,而Web前端则通常都是依照UI界面的视图区块View来进行模块化,这样的模块实际上只是Component组件,不具备独立自治的能力。究其原因我想是因为在晚期Web1.0的时代,前端的职能就是仅仅作为后端API数据的一个Render渲染器,所以前后端的视线和格局呈现了分化,也导致很多人说前端基本无架构之说。

然而web生态倒退到明天,浏览器越来越弱小,赋能越来越多,甚至不亚于一个小型操作系统,这时候的Web前端早已不是当初简略的数据渲染器,状态治理、会话维持、数据长久化、文件缓存、通信协议...随着PWA、小程序、快利用的推广,WebAPP不再是瘦客户端,慢慢成长为大胖小子。

此时的咱们该当跳出“渲染器”的井口,而从一个残缺的软件工程来思考咱们的前端架构,Web前端不只是一层View、一个GUI,咱们须要回归到与后端统一的以业务畛域为驱动的模块化视角。

为什么前端须要“微模块”?

  • 从开发角度来说:咱们须要高内聚、低耦合的涣散构造体,而不是牵一发而动全身的巨石利用,这不论是对于开发、保护、还是前期渐进式重构,都至关重要。

    前端Leader:通过一年多的迭代和人员变动,咱们代码曾经凌乱不堪了,开发越来越吃力,必须要重构,否则玩不上来了!产品经理:嗯,我了解,这外面也有很多是咱们需要变更频繁引起的,我反对你们重构!前端Leader:感激大佬了解,那新需要先停下来,等咱们重构好了再迭代吧?产品经理:你们重构要多久?前端Leader:产品这么简单了,预计至多要3个月左右吧。产品经理被吓出一身冷汗:大佬,你要3天还能够思考,停下来3个月预计公司都要关门了...前端Leader:可是产品这么简单,几天工夫实现重构是天方夜谭。产品经理想了想:这样把,我每个迭代少安顿几个需要,这样你们每个月就能够留几天工夫重构了。前端Leader:这可不是1+1=2的问题,而是0与1的问题,大佬你不理解!产品经理:谁说我不理解,你们就不能渐进式重构吗?前端Leader:...

    此时如果咱们的前端工程是基于“微模块”,一来能够轻松的找到“部分重构”的边界,二来也能够通过维持“微模块”的对外接口来无极替换。

  • 从产品角度来说:软件架构永远是服务于业务需要的。咱们心愿咱们的产品能像搭积木一样按需组合,能够疾速包装出各种灵活多样的套餐,以满足客户越来越精细化的定制需要。

    某个大型利用蕴含A,B,C,D,E,F,G等若干性能,原来始终是整体打包发售...随着用户需要的多样化,有的用户仅须要局部性能,于是聪慧的前端架构师“小李”利用时下风行的微前端技术,将利用拆分成了的 3 个子利用:- 【根底利用】蕴含性能:A- 【子利用A】蕴含性能:B,C,D- 【子利用B】蕴含性能:E,F,G这样等于有 3 个套餐能够供客户抉择:- 套餐A:根底利用 + 子利用A- 套餐B:根底利用 + 子利用B- 套餐C:根底利用 + 子利用A + 子利用B然而用户的需要越来越精细化,有的须要ABCD,有的须要ACEG,有的须要ABDF...而且同一个性能可能还存在需要版本的不同,这让“小李”无可适从。

    当初咱们利用“微模块”来帮忙小李解决问题:

    • 将各种独立的业务性能封装成不同的微模块:A,B,C,D,E,F,G
    • 将各种微模块按需要迭代版本,公布成NPM包
    • 某客户须要 A,C1(C性能的某个版本),E2(E性能的某个版本),G 性能,咱们独自为该客户创立一个聚合工程分支,装置相应版本的微模块:npm install A C@1 E@2 G

咱们晓得世界上有一款建站神器wordpress,已经号称世界上50%的网站都是由它创立的,我认为它的胜利秘诀就是社区模版机制和性能插件化,你要什么性能都总能找到“前端+后端”一起打包装置的插件,这也相似于“微模块”的概念。
  • 从工程的角度来说:“微模块”是跨工程、跨我的项目共享通用业务代码的现实决计划,对于跨端、跨平台复用业务逻辑尤其有用。

前端“微模块”的划分准则与边界

  • 领有高内聚、低耦合的工程构造。
  • 领有独立自治的子域逻辑。

从图中能够看到,每个微模块负责定义和保护本人畛域内的事务,并且麻雀虽小,五脏俱全,领有独立的路由解析、状态治理、数据模型、控制器、视图、组件、资源、业务实体、API治理等等...总之,所有与本人畛域相干的资源都被内聚到了一起。

以下是某巨石利用的SRC目录,其特点是以“文件职能”作为一级分类、“功能模块”作为次级分类:

├─ src│  ├─ api                 # API接口治理│  ├─ assets              # 动态资源文件│  ├─ components          # 全局组件│  ├─ config              # 全局配置项│  ├─ enums               # 我的项目枚举│  ├─ hooks               # 罕用 Hooks│  ├─ language            # 语言国际化│  ├─ layout              # 框架布局│  ├─ routers             # 路由治理│  ├─ store               # store│  ├─ styles              # 全局款式│  ├─ typings             # 全局 ts 申明│  ├─ utils               # 工具库│  ├─ views               # 我的项目所有页面│  ├─ App.vue             # 入口页面│  └─ main.ts             # 入口文件

以下是Elux中基于微模块的SRC目录,其改良是将“功能模块”作为一级分类,“文件职能”作为次级分类:

src├── modules│      ├──  ModuleA│      │     ├── entities│      │     ├── assets│      │     ├── api│      │     ├── utils│      │     ├── language│      │     ├── components│      │     ├── views│      │     ├── model.ts│      │     └── index.ts│      │ │      ├── ModuleB│      ├── ModuleC

微模块的台前与幕后

前端开发最终出现的是UI界面,但这只是表象,撑持UI界面渲染和交互的是背地一系列state、model、controller等幕后英雄,它们依据本人所属不同畛域被封装在各个微模块中,UI既然与它们唇齿相依,必然也将追随它们内聚在一起。

View和Component

实质上说View就是一个Component,但咱们从架构的思维来辨别它们:

  • View:业务视图,它用来体现业务规定与逻辑,通常可能较为独立和残缺的解决某一畛域问题。
  • Component:UI组件,它用来体现渲染规定与交互逻辑,通常不与具体业务间接相干,可复用在各种不同业务场景中。

所以在“微模块”的架构中,丰富多彩的UI界面由一个个繁多职责的View聚合而成,每个View同样根据本身所解决的畛域问题而被扩散在各个微模块中,这外面有几个留神点:

  • 畛域性:View被归属到不同微模块的准则是其解决的问题畛域,而不是视觉上的几何空间。View能够在视觉上被拆装、聚合、嵌套,这并不影响它们所属微模块。
  • 完整性:一个View通常能解决一个较为独立和残缺的问题,View与View之间是较为涣散的关系,如果2个View之间分割严密,那就不该当拆分它们。

不以视觉延长和几何空间作为View的微模块归属准则:如下图所示,假如有一个View用来展现用户材料,咱们将其放在UserModule这个微模块中,称其为UserModule.DetailView,但你发现其中又蕴含一个该用户发表文章的列表,你当然能够把这个列表独自提取进去作为一个新的View。从视觉上来看,它仿佛和用户材料是连在一起的,仿佛能够和UserModule.DetailView放在同一个微模块中;但咱们从它解决的问题来看,它属于文章畛域,而与用户畛域关系并不大,所以咱们最好将其放在ArticleModule中,称其为ArticleModule.ListView

前端“微模块”的实现计划

  1. 定义和创立微模块,可借助于Eluxjs框架,当然你发现了其它框架也能够。
  2. 治理微模块,可借助于NPM仓库。
  3. 应用微模块,可借助于打包工具:

    • 动态编译:微模块作为一个NPM包被装置到工程中,通过打包工具(如webpack)失常编译打包即可。这种形式的长处是代码产物失去打包工具的各种去重和优化;毛病是当某个模块更新时,须要整体从新打包。
    • 动静注入:利用Module Federation,将微模块作为子利用独立部署,与时下风行的微前端相似。这种形式的长处是某子利用中的微模块更新时,依赖该微模块的其它利用无需从新编译,刷新浏览器即可动静获取最新模块;毛病是没有打包工具的整体编译与优化,代码和资源容易反复加载或抵触。

微模块 vs 微前端

从本意上来说,微模块只是一种工程构造和模块化计划,而微前端只是它的一种利用场景之一。微模块架构不仅能够用来构建简单的单体利用,也能够联合Module Federation实现多子利用独立部署的“微前端”。

如果独自就微模块 + ModuleFederation形式实现的微前端,与传统意义上的qiankun、icestark等微前端计划相比,微模块形式胜在粒度更细、更灵便、更笨重,而传统形式则胜在隔离性更好。

想到一个十分形象的比喻:

IFrame vs 微前端 vs 微模块 可类比于 过程 vs 线程 vs 协程

从左至右:越来越轻量化,隔离性逐步变弱,灵活性逐步减少。所以鱼与熊掌不可兼得,具体哪种计划最适宜还得看不同的产品需要。

微模块之间的通信

  • 微模块之间依照某些规定和约定共享同一个Runtime,强制隔离性较弱,所以它们之间的通信是轻量级的,能够互相援用与调用。
  • 倡议观察者模式,或者应用事件总线模式来放弃微模块之间的涣散关系,这是另一个故事,可参考Eluxjs中的ActionBus
  • 微模块高内聚、低耦合的划分准则,也意味着微模块之间不会呈现特地简单的互动与交换(互动亲密的微模块该当合并)。

落地与实战

光练不说傻把式,光说不练假把式,这里先把思路概念要说的说完,上面就要开始出实例了。先喝口水,请听下回分解...急性子也能够间接去Eluxjs官网,看看Demo,不吝赐教...