Open peng-yin opened 2 years ago
微前端架构具备以下几个核心价值:
技术栈无关 主框架不限制接入应用的技术栈,微应用具备完全自主权
独立开发、独立部署 微应用仓库独立,前后端可独立开发,部署完成后主框架自动完成同步更新
增量升级 在面对各种复杂场景时,我们通常很难对一个已经存在的系统做全量的技术栈升级或重构,而微前端是一种非常好的实施渐进式重构的手段和策略
独立运行时 每个微应用之间状态隔离,运行时状态不共享 微前端架构旨在解决单体应用在一个相对长的时间跨度下,由于参与的人员、团队的增多、变迁,从一个普通应用演变成一个巨石应用(Frontend Monolith)后,随之而来的应用不可维护的问题。这类问题在企业级 Web 应用中尤其常见。
为什么不是iframe , 看这里 Why Not Iframe
该设计方案需要2类域名配合, 分别为应用域名, 网关域名. 非CDN部署模式下, 网关域名为可选项. 可以与主应用保持一致.
└── html/ # 根文件夹 | ├── app/ # 存放所有微应用的文件夹 | ├── vue-hash/ # 存放微应用 vue-hash 的文件夹 | ├── vue-history/ # 存放微应用 vue-history 的文件夹 | ├── react-hash/ # 存放微应用 react-hash 的文件夹 | ├── react-history/ # 存放微应用 react-history 的文件夹 | ├── angular-hash/ # 存放微应用 angular-hash 的文件夹 | ├── angular-history/ # 存放微应用 angular-history 的文件夹 ├── index.html # 主应用的index.html ├── css/ # 主应用的css文件夹 ├── js/ # 主应用的js文件夹
本设计遵循DDD设计拆分, 与后端相关微服务对齐
即拦截路由,并做好资源缓存,在路由切换的合适时机卸载前路由的资源,加载新路由的资源。
优化上,可以做资源prefetch,做好sandbox,子应用之间的js/css不会互相污染。
不足:目前在主应用与子应用之间的样式污染处理上,还需要做一些处理
qiankun是如何完善single-spa中留下的巨大缺口-————加载函数,JS沙箱 ,CSS样式隔离。
qiankun如何隔离子应用的js的全局环境————通过沙箱。
沙箱的隔离原理是什么————在支持proxy中有一个代理对象,子应用优先访问到了代理对象,如果代理对象没有的值再从window中获取。如果不支持proxy,那么通过快照,缓存,复原的形式解决污染问题。
qiankun如何隔离css环境————shadowDOM隔离;
// index.js - js部分只需要把window对象里面的方法赋值到开发包里 const baseSDK = window.baseSDK || {}; export default { report: baseSDK.report || {}, }; // index.d.ts declare module '@sdk' { namespace report { function pv(cid: string, data?: Object): any; function mc(bid: string, data?: Object): any; function mv(bid: string, data?: Object): any; function me(bid: string, data?: Object): any; } }
我们把更新的时机放到了子工程本地启动的时候,在启动前利用prestart钩子做一个node的版本检查和自动更新。用户选择是否去更新sdk包,参考代码:
// package.json - 在npm start 时, prestart提示安装最新的包 "scripts": { "start": "cross-env NODE_ENV=development DEPLOY_TYPE=development webpack serve --config=./config/webpack.config.js", "prestart": "node ./preStart.js", }
我们把基座工程部署到了一个特有的域名下面,里面去加载子工程,这样避免了启动两个工程开发。但是子工程一开始热更新失效,报错跨域。
1)为什么会跨域?哪里引起的跨域?
首先基座已经配置过对localhost.xx.com的域名跨域,那么问题就出现在热更新资源的问题,webpack-dev-server的热更新其实是node客户端和浏览器之间用ws双工通信去监听文件编译发请求下载薪的hot代码,然后检查发现webpack-dev-server请求的还是localhost这个域名,这个域名和我们配置的localhost.xx.com域名发生了跨域导致热更新失败,然后就去webpack5的文档里找设置webpack-dev-server域名配置方法,最终配置方法如下:
devServer: { host: 'localhost.xx.com', firewall: false, hot: true, client: { host: 'localhost.xx.com', port: devPort, needClientEntry: !IS_REMOTE_DEV, needHotEntry: !IS_REMOTE_DEV, } ... } // 更新模块重新执行 if(module.hot){ module.hot.accept() }
访问主工程域名, 加载本地子工程资源
解决办法 :在子项目注册时将主项目的路由实例对象传过去,子项目挂载到全局,用父项目的这个 router 跳转就可以了。
项目通信 qiakun 提供了一个全局的 GlobalState 来共享数据。主项目初始化之后,子项目可以监听到这个数据的变化,也能提交这个数据。
css 污染问题 主项目要想不被子项目的样式污染,项目本身的 id/class 需要特殊一点,不能太简单,被子项目匹配到。类名这需要规范
其他
1). js 沙箱并不能解决所有的 js 污染,用 onclick 或 addEventListener 给
2). qiankun 框架不太好实现 keep-alive 需求,因为解决 css/js 污染的办法就是删除子项目插入的 css 标签和劫持 window 对象,卸载时还原成子项目加载前的样子,这与 keep-alive 相悖: keep-alive 要求保留这些,仅仅是样式上的隐藏。
3). qiankun 将每个子项目的 js/css 文件内容都记录在一个全局变量中,如果子项目过多,或者文件体积很大,可能会导致内存占用过多,导致页面卡顿。
4). qiankun 运行子项目的 js,并不是通过 script 标签插入的,而是通过 eval 函数实现的,eval 函数的安全和性能是有一些争议
1、名词解释
2、设计背景
微前端架构具备以下几个核心价值:
技术栈无关 主框架不限制接入应用的技术栈,微应用具备完全自主权
独立开发、独立部署 微应用仓库独立,前后端可独立开发,部署完成后主框架自动完成同步更新
增量升级 在面对各种复杂场景时,我们通常很难对一个已经存在的系统做全量的技术栈升级或重构,而微前端是一种非常好的实施渐进式重构的手段和策略
独立运行时 每个微应用之间状态隔离,运行时状态不共享 微前端架构旨在解决单体应用在一个相对长的时间跨度下,由于参与的人员、团队的增多、变迁,从一个普通应用演变成一个巨石应用(Frontend Monolith)后,随之而来的应用不可维护的问题。这类问题在企业级 Web 应用中尤其常见。
为什么不是iframe , 看这里 Why Not Iframe
4、域名规划
该设计方案需要2类域名配合, 分别为应用域名, 网关域名. 非CDN部署模式下, 网关域名为可选项. 可以与主应用保持一致.
5、路径结构设计
6、部署目录设计
6、activeRule详细列表
本设计遵循DDD设计拆分, 与后端相关微服务对齐
3、基本原理
即拦截路由,并做好资源缓存,在路由切换的合适时机卸载前路由的资源,加载新路由的资源。
优化上,可以做资源prefetch,做好sandbox,子应用之间的js/css不会互相污染。
不足:目前在主应用与子应用之间的样式污染处理上,还需要做一些处理
通过图示具体理解一下 qiankun 注册子应用的过程:
整个qiankun框架中我们知道了什么东西:
qiankun是如何完善single-spa中留下的巨大缺口-————加载函数,JS沙箱 ,CSS样式隔离。
qiankun如何隔离子应用的js的全局环境————通过沙箱。
沙箱的隔离原理是什么————在支持proxy中有一个代理对象,子应用优先访问到了代理对象,如果代理对象没有的值再从window中获取。如果不支持proxy,那么通过快照,缓存,复原的形式解决污染问题。
qiankun如何隔离css环境————shadowDOM隔离;
实际开发中遇到的问题
我们把更新的时机放到了子工程本地启动的时候,在启动前利用prestart钩子做一个node的版本检查和自动更新。用户选择是否去更新sdk包,参考代码:
我们把基座工程部署到了一个特有的域名下面,里面去加载子工程,这样避免了启动两个工程开发。但是子工程一开始热更新失效,报错跨域。
1)为什么会跨域?哪里引起的跨域?
首先基座已经配置过对localhost.xx.com的域名跨域,那么问题就出现在热更新资源的问题,webpack-dev-server的热更新其实是node客户端和浏览器之间用ws双工通信去监听文件编译发请求下载薪的hot代码,然后检查发现webpack-dev-server请求的还是localhost这个域名,这个域名和我们配置的localhost.xx.com域名发生了跨域导致热更新失败,然后就去webpack5的文档里找设置webpack-dev-server域名配置方法,最终配置方法如下:
访问主工程域名, 加载本地子工程资源
解决办法 :在子项目注册时将主项目的路由实例对象传过去,子项目挂载到全局,用父项目的这个 router 跳转就可以了。
项目通信 qiakun 提供了一个全局的 GlobalState 来共享数据。主项目初始化之后,子项目可以监听到这个数据的变化,也能提交这个数据。
css 污染问题 主项目要想不被子项目的样式污染,项目本身的 id/class 需要特殊一点,不能太简单,被子项目匹配到。类名这需要规范
其他
1). js 沙箱并不能解决所有的 js 污染,用 onclick 或 addEventListener 给
添加了一个点击事件,js 沙箱并不能消除它的影响,还得靠代码规范2). qiankun 框架不太好实现 keep-alive 需求,因为解决 css/js 污染的办法就是删除子项目插入的 css 标签和劫持 window 对象,卸载时还原成子项目加载前的样子,这与 keep-alive 相悖: keep-alive 要求保留这些,仅仅是样式上的隐藏。
3). qiankun 将每个子项目的 js/css 文件内容都记录在一个全局变量中,如果子项目过多,或者文件体积很大,可能会导致内存占用过多,导致页面卡顿。
4). qiankun 运行子项目的 js,并不是通过 script 标签插入的,而是通过 eval 函数实现的,eval 函数的安全和性能是有一些争议