qiankun

一、为什么需要微前端

1.what什么是微前端

将不同功能按照不同维度拆分成多个子应用,通过主应用加载子应用。
微前端核心:在于拆,拆完后再合。
例如:

网厅项目:(1)已经实现的基座(中信方正),子应用:方正obs-fcf,中信obs-zx,中信自研zx-online
(2)即将开发的场景机构预约开户考虑怎么拆分,放在基座还是子应用,公共模块

2.why为什么使用

(1)技术栈不同解决协同(vue, react , angle, jquery)
(2)团队独立开发部署
(3)老的应用代码,老的应用很稳定,如果重构时间不允许,稳定性短时间无法保证

3.how怎么去落地微前端

架构方案:
(1)singleSPA
核心功能实现了路由劫持和应用加载
缺点:1.没有处理父子应用或者平级应用的css样式隔离
2.js未执行隔离,都使用window,命名一致的话相互覆盖
(2)qiankun
qiankun:基于singleSPA t提供了开箱即用的API,做到了(singleSPA + sandbox + import-html-entry),与技术栈无关,通过协议接入(子应用必须导出bootstrap,mount,unmount方法供父应用调用)

4.Why Not Iframe

(1)iframe 最大的特性就是提供了浏览器原生的硬隔离方案,不论是样式隔离、js 隔离这类问题统统都能被完美解决。但他的最大问题也在于他的隔离性无法被突破,导致应用间上下文无法被共享,随之带来的开发体验、产品体验的问题。
(2)

  1. url 不同步。浏览器刷新 iframe url 状态丢失、后退前进按钮无法使用。
  2. UI 不同步,DOM 结构不共享。想象一下屏幕右下角 1/4 的 iframe 里来一个带遮罩层的弹框,同时我们要求这个弹框要浏览器居中显示,还要浏览器 resize 时自动居中…
  3. 全局上下文完全隔离,内存变量不共享。iframe 内外系统的通信、数据同步等需求,主应用的 cookie 要透传到根域名都不同的子应用中实现免登效果。
  4. 慢。每次子应用进入都是一次浏览器上下文重建、资源重新加载的过程。

(3)举例。中信机构线上化pdf协议阅读签署。
使用:
dom拓展性差,监听滚动到底(无法监听,通过ele.contentWindow可以,但兼容性极差)

F25C651F-360B-4c8f-92DE-5370CF9B471F.png

二、实战

1.singleSPA实战

(1)构建子应用

// main.js

import Vue from 'vue'
import App from './App.vue'
import router from './router'
import singleSpaVue from 'single-spa-vue'

Vue.config.productionTip = false

// 步骤一:

const appOptions = {
  el: '#vue', // 挂载到父应用的id为vue的标签中
  router,
  render: h => h(App)
}
const vueLifeCycle = singleSpaVue({
  Vue,
  appOptions
})

// 协议接入,定好协议,未来父应用会调用这些方法
export const boostrap = vueLifeCycle.bootstrap
export const mount = vueLifeCycle.mount
export const unmount = vueLifeCycle.unmount

// 步骤二: 父应用加载子应用,将子应用打包成一个个lib给父应用使用

// 步骤三: 细节处理
// 处理公共路径,处理独立加载

(2)子应用配置库打包

// vue.config.js
module.exports = {
  configureWebpack: {
    output: {
      library:'singleVue', // lib名称
      libraryTarget:'umd' // 格式
    },
    devServer: {
      port: 10000
    }
  }
}

(3)主应用搭建

// main.js
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import { registerApplication, start} from 'single-spa'

Vue.config.productionTip = false

async function loadScript(url) {
  return new Promise((resolve,reject)=>{
    let script = document.createElement('script')
    script.src = url
    script.onload = resolve
    script.onerror = reject
    document.head.appendChild(script)
  })

}

registerApplication('myVueApp',
async ()=>{
  console.log('load')
  await loadScript('http://localhost:10000/js/chunk-vendors.js')
  await loadScript('http://localhost:10000/js/app.js')
  return window.singleVue; // boostrap mount unmount
},
location => location.pathname.startsWith('/vue') // 用户切换到/vue的路径下,需要记载刚才定义的子应用
)

start()

new Vue({
  router,
  render: h => h(App)
}).$mount('#app')


// 一:注册子应用  registerApplication
// 二:加载子应用文件 loadScript
// 三:细节处理 路由匹配,加载容器

(4)到目前为止的问题总结:

1.基础路径不是以/vue(待处理)

base: '/vue'

2.动态设置子应用的publicPath

window.singleSpaNavigate // 标识
__webpack_public_path__ // 设置值 'http://localhost:10000/'

3.webpack_public_path暂时不能独立运行;(待处理)
new Vue(appOptions).$mount('#app')

4.父子应用css没有隔离;

父应用样式:3E807CC3-70A2-463a-A0AA-049BB5293742.png

子应用加载后样式:

C7A1AF9D-E358-4e9a-9E44-DF269E33E54C.png

5.不够灵活不能动态加载js文件;

5082D7DB-E7C3-4c77-9D32-B953507CA197.png

24F995B5-A613-4371-B886-6A3AB2FE1644.png

6.没有js沙箱机制,全局变量覆盖;

父:window.a 子:window.a相互覆盖

(5)singleSpa整理流程来一个梳理;

父应用做了什么事:

微信图片_20220324142930.png

1.注册子应用
2.引入子应用文件
3.准备容器
4.匹配路由
子应用做了什么事情:

微信图片_20220324144224.png
1.引入生态,暴露方法。

export const boostrap = vueLifeCycle.bootstrap
export const mount = vueLifeCycle.mount
export const unmount = vueLifeCycle.unmount

2.子应用配置库打包

module.exports = {
  configureWebpack: {
    output: {
      library:'singleVue',
      libraryTarget:'umd'
    },
    devServer: {
      port: 10000
    }
  }
}

3.基础路径webpack_public_path设置
4.base路径’/vue’设置
5.子应用独立运行

2.qiankun实战

(1)主应用编写

引入,注册,启动22D53DD4-EE2D-4e9c-9A7B-E2B871B5E6E6.png

准备容器,匹配路由

84D20885-1D01-4927-B5BE-E2B2F05DFE6C.png主应用做了什么?
92084662-3F23-4c86-B798-19157501FD0A.png

(2)子vue应用

接入协议:暴露三个方法(调用方法加载,卸载)

932AAA36-D230-4337-8013-EA9C1DA02D35.png
设置打包类库,支持跨域
9EFDDF8B-D64C-45fa-BC90-66FEFA93CBDD.png
基础路径
DB93C81A-0D8A-4183-A791-B4170F621E32.png

(3)子react应用
接入协议:暴露三个方法(调用方法加载,卸载)
EC2C3EDC-4678-4e98-ABE2-E8FBC212C8B7.png
设置打包类库,支持跨域
BE569C33-2C07-4ce7-AD8F-C8C14B93F436.png

基础路径

C48FB97B-571A-454e-81B2-E506FAA69D77.png

三、css隔离方案

1.子应用之间样式隔离动

乾坤实现的是:动态样式表,当应用切换时移除老样式,添加新应用的样式

2.主应用和子应用之间的样式隔离

约定项目前缀(既然是约定,肯定会有不遵守)
css-modules 打包时生成不冲突的选择器名
shadom dom 处理父子应用真正意义上的隔离

3.shadom dom

  <div>
    <p>hello world</p>
    <div id="shadow"></div>
  </div>
  <script>
    let shadowDOM = document.getElementById('shadow').attachShadow({mode:'closed'})
    let pElm = document.createElement('p')
    pElm.innerHTML = 'hello china'
    let styleElm = document.createElement('style')
    styleElm.textContent = `p{color:red}`
    shadowDOM.appendChild(styleElm)
    shadowDOM.appendChild(pElm)

  </script>

0CA197D3-D4E2-47bf-AD78-2BD2CF856489.png
062B804A-AC84-4b7c-AF06-4D9E623381F2.png

4.代码 shadow-dom

四、js沙箱机制(快照沙箱)

1.沙箱是什么:

(1)就是让你的程序跑在一个隔离的环境下,不对外界的其他程序造成影响;
(2)单应用切换时, 沙箱:创造一个干净的环境给子应用使用,当切换时可以选择丢弃和回复属性

2.快照沙箱: 一年前拍一张照片 一年后再拍一张 (将前后对比的区别保存起来) 应用: 将区别应用回到一年前 或者是回复到一年前后再此恢复到当前
3.现象
9FF62CE2-9D0E-47a2-94B3-5E0E4C6433B5.png
4.代码sandbox
5.图形理解链路

激活

微信图片_20220329134305.png

失活
微信图片_20220329134310.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值