方式一
- 采用注册中心(Register-Center)
- 路由监控(Router-Moniter)
- 模块加载器(Page-loader) 基于上面三种方式实现微前端框架
实现思路
- 1: 注册中心的功能
- 每个微应用打包后,将打包后的入口js文件地址,与匹配的路由上传到注册中心
- 进入基座应用后,通过接口到注册中心获取所有的微应用路由和对应的目标js地址
- 2: 路由监控的功能
- 基座应用通过a标签渲染所有的路由
- 通过Router-Moniter监听页面所有的a标签点击,获取a标签的href属性是否与注册中心返回的路由一致
- 3: 模块加载器的功能
- 发现一致,就通过Page-loader加载和执行对应href属性值对应的的入口js文件。
- 被加载的微应用js文件提供mount和unMount方法供基座应用的调用。
- 加载完成后缓存这个文件,提高后续二次加载的性能。
问题:
- 问题一:子应用采用上面样的打包方式
采用UMD的方式来打包,这样我们就可以在全局环境下获取到对应的微应用模块并执行
- 问题二:webpack采用webpackJsonpCallback来加载和调用异步的js模块。 那每个微都会打包出一个全局的webpackJsonpCallback用来加载异步js。这样岂不是存在互相覆盖的情况该如何处理?
处理方式1:webpack5之前的处理方式,在配置文件中显示的声明jsonpFunction的别名
const pkg = require('./package.json')
output: {
jsonpFunction: pkg.name; // 指定打包后的webpackJsonpCallback的别名,反之不同微应用打包后的jsonpFunction互相覆盖
}
处理方式2:在webpack5中则不需要我们自己声明好配置文件中的jsonpFunction,webpack5会自动到项目的package.json中读取name属性的值作为jsonpFunction的别名。
- 被加载的微应用js文件提供mount和unMount方法供基座应用的调用。
基座应用加载完js后调用js暴露的mount方法,将微应用挂载到对应的节点,路由切换前卸载调用unMount卸载对应的微应用。
方式二
-
采用webpack5的模块联邦(Module-Federation)实现微前端架构 关键是ModuleFederationPlugin插件
-
子应用中的配置
const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin')
module.exports = {
...
devServer: {
port: 8089
},
plugins: [
new ModuleFederationPlugin({
name:'moduleA', //当前子应用对外导出的名称,必须是唯一的${name}/${expose} 的方式使用;
filename:'remoteEntry.js', // 构建出来的文件名
exposes:{ // 当前子引用作为导出的模块的入口文件
'./index':'./src/index'
},
shared:['react','react-dom'] //可选,优先用 Host 的依赖,如果 Host 没有,再用自己的;
})
]
}
- 基座应用的配置
const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin')
module.exports = {
...
devServer: {
port: 8081
},
plugins: [
new ModuleFederationPlugin({
remotes:{
// @符号前的moduleA为基座应用ModuleFederationPlugin配置的name
// @符号后的为子应用打包后的入口js文件地址
remote:'moduleA@http://localhost:8089/remoteEntry.js'
},
shared:['react','react-dom']
})
]
}
- 通过webpack5中模块联邦(Module-Federation)实现shared模块的复用。
所有子应用中公用的业务组件,ui组件,工具函数等都可以通过Module-Federation的shared配置实现模块的复用。做到公用模块的按需加载和复用。
- 被加载的微应用js文件提供mount和unMount方法供基座应用的调用。
基座应用加载完js后调用js暴露的mount方法,将微应用挂载到对应的节点,路由切换前卸载调用unMount卸载对应的微应用。
微应用中的样式隔离
css的常见的模块化方案
- 1:css-in-js
style-components是典型的css-in-js方案,可以实现css的作用于隔离 需要安装style-components并在webpack中进行对应的配置
- 2:css-module
需要与webpack中css-loader配置即可
- 3:Bem
Bem更多的只能算是一种规范,要开发去约定和准守这个规范。(规范的话还是需要人更多的参与,旧就存在不可控的可能。相对说还是Bem与上面的方案配合)
- 4:ShadowDom
借用浏览器的能力,支持ShadowDom的浏览器能自带样式隔离
后续补充。。。