SingleSpa微前端基本使用以及原理

news/2024/4/29 12:39:32

先说说singleSpa的缺点

  • 不够灵活 不能动态加载css文件
  • css不隔离
  • 没有js沙箱的机制 ( 没有全局对象 每次切换的应用 都是同一个window )

但是刚刚接触微前端 可以了解一下微前端的基础使用
qiankun微前端框架已经很成熟 也是基于singleSpa来实现的
点击跳转qiankun的基础使用

大致实现思路 (不了解微前端概念的可以去自行了解)

  • 首先在父应用注册一个应用
  • 当条件满足的时候(匹配路径) 会加载我们另一个子应用的脚本
  • 加载子应用用脚本的话
    – 那在我们子应用打包的时候 , 自身上就有一些类库了
  • 父应用加载到子应用的类库时候 就会调用子应用身上的一些方法了
    – 这个时候 类库就会把子应用整体的dom 放在( 挂载 )到父应用上面去
  • 而且我们要保证子应用自身引用的所有路径 都是相对于自身的绝对路径
    – 不然在父应用里使用子应用的一些操作 调用的是父应用的根路径 就会出问题

首先创建两个应用

一个子应用 各个父应用

在这里插入图片描述

我们需要父应用加载子应用 需要在子应用导出三个方法
bootstrap mount unmount ( SingleSpa的规定 )

vue的项目需要npm安装 Single-spa-vue
react的项目需要npm安装 Single-spa-react

初始化子应用

npm安装single-spa-vue

  • 配置main.js
import Vue from 'vue'
import App from './App.vue'
import router from './router'// 引入singleSpaVue的包
import singleSpaVue from 'single-spa-vue'
Vue.config.productionTip = false//子应用不能直接挂载
// new Vue({   
//   router,
//   render: h => h(App)
// }).$mount('#app')// 而是封装成一个对象
const appOptions = {el:'#vue',  // 增加一个属性挂在到父应用的 id为vue的标签上router,render: h => h(App)
}// 把vue和上面这个对象传入进去  这个singleSpaVue就会返回vueLife
// vueLife是包装好的生命周期  对应的就是bootstrap mount unmount  这三个方法
const vueLife = singleSpaVue({Vue,appOptions
})//导出这三个方法  
//协议接入  我定好了这些方法  父应用会调用这些方法
export const bootstrap = vueLife.bootstrap
export const mount = vueLife.mount
export const unmount = vueLife.unmount
  • 我们需要父应用加载子应用 需要打包成一个个的lib去给父应用使用
  • 如何打包呢 在vue.config.js中配置
module.exports = {configureWebpack:{output:{// 给类库取一个名字library:'singleVue',// 指定模块类型  umd 会把打包后那三个属性挂在window上 //比如 window.bootstrap / window.mount / window.oumountlibraryTarget:'umd' },devServer:{port:10000 }}
}

初始化父应用

npm安装single-spa (不要加vue)

  • App.vue中处理结构
<template><div id="app"><!-- 路由中没写/vue这个路径  说明路由匹配不到  但是可以去匹配这个路由来加载子应用  --><router-link to="/vue">加载vue子应用</router-link><!-- 这个id = vue就是子应用main.js中el挂载的#vue --><div id="vue"></div></div>
</template>
  • 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// 注册应用  参数1 注册一个名字  参数2 一点要是个promise函数
registerApplication('myVueApp',async()=>{// 如果路径为 /vue  就会调用现在这个方法了   但是这个方法必须要导出子应用下的那三个方法 (不导出会报错) // 但是这个三个方法在哪里呢  请看下面的图片 具体写法先写如下// 动态创建script标签 把这个模块引入进来  (加载顺序要先加载公共的  再加载自己的 )await loadScript('http://localhost:10000/js/chunk-vendors.js')await loadScript('http://localhost:10000/js/app.js')// 这样就可以导出window上的lib包了  'singleVue'就是vue.config.js配置的包名 return window.singleVue //bootstrap mount onmount},// 参数3 用户切换到/vue路径下 需要加载刚刚定义的子应用location=>location.pathname.startsWith('/vue')
)// 处理上面参数2的promise
async function loadScript(url){// js加载是异步的 所以要用promisereturn new Promise((resole,reject)=>{let script = document.createElement('script')script.src = urlscript.onload = resole // 加载成功script.onerror = reject //加载失败document.head.appendChild(script) //把script放在html的head标签里 })
}// 开启应用
start()new Vue({router,render: h => h(App)
}).$mount('#app')

在这里插入图片描述

  • 这样就开启了基础的嵌入子应用
    在这里插入图片描述
  • 点击按钮后 ( 但是还有问题 )
  • css没有隔离 ( 使用到了子应用的css 导致标签就居中了 )
  • 点击子应用的路由 跳转会错误
    – 路径上的/vue会消失( 点击子应用的路由 但是跳转的是父应用的路由 )
    – 需要在子应用中虚拟一个路径
    在这里插入图片描述

给子路由配置基础路径

  • 子应用的router/index中
const router = new VueRouter({mode: 'history',// base: process.env.BASE_URL, //删除原本的//点击子应用的路由的时候 需要通过/vue去加载base: '/vue', routes
})
  • 但是还有个问题 每次点击子路由的时候 加载的是父应用上的路由
    – 我们需要操作子应用的时候 匹配的是子应用自身的路径
    – 解决方法 : 我们请求的每一个路由 都要加载的是自身的根路径才行
    -在子应用的main.js中配置
    主要看if(window.singleSpaNavigate){}后面的新增代码
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import singleSpaVue from 'single-spa-vue'
Vue.config.productionTip = falseconst appOptions = {el:'#vue',  router,render: h => h(App)
}const vueLife = singleSpaVue({Vue,appOptions 
})//加上了如下的判断
//如果父应用引用我的时候
if(window.singleSpaNavigate){// 动态的设置一个属性 打包的时候加上一个目录 目录就是自身的根路径// 这样的时候我们发请求的时候 都会把这个路径拼到最前面 变成一个绝对路径__webpack_public_path__ = 'http://localhost:10000/'
}
//我们还需要让子应用独立运行 (如果父应用没有引用我的时候)
if(!window.singleSpaNavigate){// 子应用独立运行的话 就是正常初始化vue了  这个挂载父应用的el就可以删除delete appOptions.el//可以正常初始化vue了  new Vue(appOptions).$mount('#app')
}export const bootstrap = vueLife.bootstrap
export const mount = vueLife.mount
export const unmount = vueLife.unmount

现在的话已经基础的实现了父应用嵌套子应用

并且子应用也可以独立运行了

在这里插入图片描述
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.cpky.cn/p/10455.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

MySQL 面试题及答案整理,最新面试题

MySQL中InnoDB和MyISAM存储引擎的区别是什么&#xff1f; InnoDB和MyISAM是MySQL中两种常见的存储引擎&#xff0c;它们的主要区别包括&#xff1a; 1、事务支持&#xff1a; InnoDB支持事务&#xff0c;而MyISAM不支持。 2、行级锁和表级锁&#xff1a; InnoDB提供行级锁&a…

数学建模-模糊性综合评价模型

中医药是中国传统文化的重要组成部分&#xff0c;凝聚了中华民族千百年来智慧的结晶。作为中医的发源地&#xff0c;中国政府一直致力于保护、发展和推广中医药&#xff0c;采取了一系列政策措施[]。目前&#xff0c;中国面临着老龄化日益加剧&#xff0c;老年人群中慢性疾病和…

AI + Science :科学研究新范式

AI 发展七十余年&#xff0c;每一技术性突破都将给人类未来开辟新一种可能性。而它与科学研究的深度融合&#xff0c;则会裂变出无数或无穷种可能性。 正文&#xff1a; 万众瞩目下&#xff0c;今年 10 月&#xff0c;有着诺贝尔奖 “嫡传” 之称的诺贝尔化学奖终于揭晓&#x…

JVM知识整体学习

前言&#xff1a;本篇没有任何建设性的想法&#xff0c;只是我很早之前在学JVM时记录的笔记&#xff0c;只是想从个人网站迁移过来。文章其实就是对《深入理解JVM虚拟机》的提炼&#xff0c;纯基础知识&#xff0c;网上一搜一大堆。 一、知识点脑图 本文只谈论HotSpots虚拟机。…

即插即用篇 | YOLOv8 引入 NAM 注意力机制 | 《NAM: Normalization-based Attention Module》

论文名称:《NAM: Normalization-based Attention Module》 论文地址:https://arxiv.org/pdf/2111.12419.pdf 代码地址:https://github.com/Christian-lyc/NAM 文章目录 1 原理2 源代码3 添加方式4 模型 yaml 文件template-backbone.yamltemplate-small.yamltemplate-large…

Python实现企业微信自动打卡程序二:跳过节假日,随机打卡时间,定时任务,失败通知

实现打卡时间随机范围 既然我们程序写完后需要定时执行&#xff0c;那定时执行打卡就会导致每次上班或下班打卡时都是同一时间&#xff0c;这并不好&#xff0c;为了避免被发现&#xff0c;每次打卡时间都是同一时间&#xff0c;这里我们优化程序&#xff0c;增加随机等待时间来…