为什么需要(小程序)微前端?
如果项目复杂,并且很多功能相对独立,那么不同的功能可以交给不同的团队开发,团队本身存在差异如技术选型等。另外的好处是,功能解耦,各功能可以独立开发、测试、部署。
web端的微前端已经有部分框架支持如qiankun
、single-spa
等等。
但是小程序层面,探索的则较少,可能和小程序的 小
有关(实际上从我个人角度看,小程序这种东西不太需要微前端这种技术),但是实际上确实有团队把小程序做的很大(毕竟做小程序的成本要小些)。
web微前端的问题
微前端框架主要需要具备如下功能(解决这些问题)
- 加载子应用:监听路由加载对应的子应用。
- 沙箱:js/style 隔离: 子应用之间、子应用与主应用之间的样式和 js 不互相影响。
- 通信:子应用之间、子应用与主应用之间的通信。
小程序微前端:问题和解决方案
参考web端需要注意的点
如何加载子应用
- **
问题1
**:运行时各应用的代码如何拉取?和web端不同,小程序不支持动态加载和执行js代码,最终的小程序应用需要作为一个整体上传到微信公众平台。该如何划分各应用的代码❓❓❓(总不能不做区分都放在主包中吧)。 - 方案:微信小程序提供了分包机制(主包、普通分包、独立分包),刚好可以利用分包来承载各子应用的代码,比如一个子应用的代码放在一个分包中。我这里会选用普通分包划分。
为什么选用普通分包而不是独立分包实现
- 独立分包的优点是不依赖主包,可以独立加载并运行,缺点是不支持插件
- 微信小程序推出了分包异步化 能力,那主包只需要提供最基础的前置代码即可比如uniapp运行时,而该特性之前的共有组件或者js现在都可以移到分包去。因此主包可以做到很小,独立分包的优势则可以被【普通分包 分包异步化】替代。
这里有个需要注意的点事:子应用中的主包页面不能放在分包中,需要放到最终产物的主包中,这和小程序框架对subPackages
的root
限制有关。(使用分包)
- **
问题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
,当然会存在很多属性需要调整,比如pages
,subPackages
,plugins
,preloadRule
等需要进行合并处理。
- **
问题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时,则会有问题,不能上传。 留给读者思考吧