「小程序微前端」 初探

2023-02-24 10:25:55 浏览数 (1)

为什么需要(小程序)微前端?

如果项目复杂,并且很多功能相对独立,那么不同的功能可以交给不同的团队开发,团队本身存在差异如技术选型等。另外的好处是,功能解耦,各功能可以独立开发、测试、部署。

web端的微前端已经有部分框架支持如qiankunsingle-spa等等。

但是小程序层面,探索的则较少,可能和小程序的 有关(实际上从我个人角度看,小程序这种东西不太需要微前端这种技术),但是实际上确实有团队把小程序做的很大(毕竟做小程序的成本要小些)。

web微前端的问题

微前端框架主要需要具备如下功能(解决这些问题)

  1. 加载子应用:监听路由加载对应的子应用。
  2. 沙箱:js/style 隔离: 子应用之间、子应用与主应用之间的样式和 js 不互相影响。
  3. 通信:子应用之间、子应用与主应用之间的通信。

小程序微前端:问题和解决方案

参考web端需要注意的点

如何加载子应用

  • **问题1**:运行时各应用的代码如何拉取?和web端不同,小程序不支持动态加载和执行js代码,最终的小程序应用需要作为一个整体上传到微信公众平台。该如何划分各应用的代码❓❓❓(总不能不做区分都放在主包中吧)。
  • 方案:微信小程序提供了分包机制(主包、普通分包、独立分包),刚好可以利用分包来承载各子应用的代码,比如一个子应用的代码放在一个分包中。我这里会选用普通分包划分。

为什么选用普通分包而不是独立分包实现

  1. 独立分包的优点是不依赖主包,可以独立加载并运行,缺点是不支持插件
  2. 微信小程序推出了分包异步化 能力,那主包只需要提供最基础的前置代码即可比如uniapp运行时,而该特性之前的共有组件或者js现在都可以移到分包去。因此主包可以做到很小,独立分包的优势则可以被【普通分包 分包异步化】替代。

这里有个需要注意的点事:子应用中的主包页面不能放在分包中,需要放到最终产物的主包中,这和小程序框架对subPackagesroot限制有关。(使用分包)


  • **问题2**:路由维度:小程序有自己的路由机制,开发者只需要在app.json中注册页面路径即可。每个应用都是有多个页面,这些页面需要显示的app.json中声明, 如果页面出现冲突怎么办呢❓❓❓
  • 方案:加一层命名空间隔离,比如A引用中的路径pages/index/index => A/pages/index/index

如何隔离js和style

小程序框架系统分为两部分:逻辑层和 视图层

  • **问题3**:首先是js:所有页面的js逻辑都是在同一个运行环境中执行,会共享全局变量,如何隔离呢❓❓❓。
  • 方案node中的vm模块能够创建真实的沙箱环境,在小程序中做不到。 这里利用闭包和变量作用域去模拟一个沙箱环境,把需要隔离的原始对象变成从函数闭包中获取。
  • **问题4**:然后是style:每个页面的视图层是完全独立的,也就是说各页面之间的dom结构和样式也是隔离的,但是各页面的样式都会受到全局样式(app.wxss)的影响,如何处理呢❓❓❓
  • 方案:只需要在当前应用中引入当前应用的全局样式文件即可,如@import ./app.wxss;还有小程序自己提供的app.json中的window属性,需要处理,否则影响全局。注意最终的产物中不能有app.wxss

如何相互通信呢?

  • 基于全局对象,封装一个通信sdk,然后注入到js沙箱中

其他问题

  • **问题5**:app.json:各应用中都有全局配置文件app.json,如何处理❓❓❓
  • 方案:我的实现中,设置了主子应用,app.json的主要内容来自主应用中的app.json,当然会存在很多属性需要调整,比如pagessubPackagespluginspreloadRule等需要进行合并处理。

  • **问题6**:app.js:对于小程序框架来说只会执行一次最外层的app.js。当我们将多个子应用合并为一个小程序时,各子应用中的app.js文件如何处理❓❓❓ App() 必须在 app.js 中调用,必须调用且只能调用一次。不然会出现无法预期的后果。
  • 方案:主应用的app.js不做更改,依然是由框架调用。app.js的主要作用是通过App()注册应用级别的生命周期,微信小程序提供了监听应用级别生命周期的方法,因此将App({onShow:fn}) => wx.onAppShow(fn) 就好,子应用app.js的执行由其他js主动引入,加载后立即执行。

总结

给出了小程序微前端应该要解决了哪些问题,以及这些问题的解决方案。看到主要是要处理有全局影响的功能:如app.jsapp.jsonapp.wxss,应用间的隔离(路由、逻辑层的代码)。

我的实现 个人项目,主要是提供一个思路。

展望

  • 目前做法是将子应用的所有页面放在一个分包中,由于分包的2M的大小限制,当一个子应用大于2M时,则会有问题,不能上传。 留给读者思考吧

0 人点赞