由于公司的项目很多都使用了微前端,近几天系统学习了基于乾坤的微前端原理,记录一下
首先,为啥要使用微前端呢,在未使用微前端之前,整个系统的所有代码全都写在一个代码仓库,每次修改了一点东西,整个系统的代码都会重新编译打包,开发过程很耗时,上线维护时有一个同学的代码需要修改,就需要整个重新构建部署维护,时间比较久,使用了微前端后,开发时打包编译的时间明显缩短提示开发效率
微前端分为两部分,一部分是主应用,也称基座应用,主要负责注册所有的子应用,监听路由的变化,基于activeRule来匹配要加载的子应用,而子应用做的事情比较简单,export自己的三个生命周期函数,使得基座应用在匹配到子路由时调用对应子应用的生命周期函数来实现子应用的加载和卸载操作
系统来说一下基座应用的处理
1.注册子应用,包括子应用名字,入口文件,子应用的dom节点挂载到哪里,子应用激活规则 接下来看下registerMicroApps()的具体实现,其实就是获取注册的子应用列表,在任何地方都能获取到注册的子应用列表
2.根据路由加载子应用,也就是start()的具体处理
第一步,监听路由变化,此处主要重写history路由,hash路由就在hashChange监听事件内追加处理路由的操作,history路由包括pushstate,replaceState以及浏览器上的前进后退操作,前进后退操作只需要在原有的功能上追加而不是重写
第二步,加载子应用,bootstrap(),mount()
根据当前的路由去子应用列表的activeRule里匹配到要加载的子应用,如果之前已经有加载的子应用就先卸载再加载现在的子应用,如何加载子应用呢?根据匹配的子应用的entry能拿到子应用的html文件,然后找出html文件中所有的script标签,得到的scripe标签是字符串,使用eval遍历执行所有的script标签生成dom元素
这里为啥要自己构造一个module和exports,我们在子应用的webpack里配置子应用打包成umd格式,具体的打包见下图,这里是为了兼容commonjs和amd格式,如果是commonjs格式,module.exports=fn(),所以我们在代码里手动构造这两个变量,吧子应用打包之后的执行结果赋值给module.exports返回出去,即得到子应用的js运行行结果
主应用定义三个周期函数,以便在需要的时候来调用子应用抛出来的生命周期函数实现子应用的挂载和卸载,会传入基座应用中挂载的节点id方便子应用知道挂载到哪里
那么接下来我们来看看子应用做了啥,子应用export三个周期函数,并根据是否传入挂载节点来实现具体的挂载地方,判断是否是在微应用中打开子应用,如果是单独打开,直接挂载在子应用定义的rooe节点上,如果是在微应用中加载子应用,则会先找到基座应用节点下的root节点进行挂载