基于vue+single-spa实现微前端的小demo

2022-08-11 14:49:40

最终实现的效果:
在这里插入图片描述

  1. vue cli

使用npm管理包自行安装基础环境啊
npm install -g @vue/cli 安装vue脚手架

  1. 创建主应用app1和子项目app2

vue create app1
vue create app2

  1. 改造主项目app1

npm i single-spa-vue -S

main.js改造

import Vuefrom'vue'import Appfrom'./App.vue'import routerfrom'./router'import{ registerApplication, start}from'single-spa'

Vue.config.productionTip=false// 远程加载子应用functioncreateScript(url){returnnewPromise((resolve, reject)=>{const script= document.createElement('script')
    script.src= url
    script.onload= resolve
    script.onerror= rejectconst firstScript= document.getElementsByTagName('script')[0]
    firstScript.parentNode.insertBefore(script, firstScript)})}// 记载函数,返回一个 promisefunctionloadApp(url, globalVar){// 支持远程加载子应用returnasync()=>{awaitcreateScript(url+'/js/chunk-vendors.js')awaitcreateScript(url+'/js/app.js')// 这里的return很重要,需要从这个全局对象中拿到子应用暴露出来的生命周期函数return window[globalVar]}}// 子应用列表const apps=[{
    name:'app2',
    app:loadApp('http://localhost:8082','app2'),activeWhen:location=> location.pathname.startsWith('/app2'),
    customProps:{}},]// 注册子应用for(let i= apps.length-1; i>=0; i--){registerApplication(apps[i])}newVue({
  router,mounted(){// 启动start()},render:h=>h(App)}).$mount('#app')

vue.config.js

constpackage=require('./package.json')
module.exports={// 告诉子应用在这个地址加载静态资源,否则会去基座应用的域名下加载
  publicPath:'//localhost:8081',// 开发服务器
  devServer:{
    port:8081},
  configureWebpack:{// 导出umd格式的包,在全局对象上挂载属性package.name,基座应用需要通过这个全局对象获取一些信息,比如子应用导出的生命周期函数
    output:{// library的值在所有子应用中需要唯一
      library:package.name,
      libraryTarget:'umd'}}}

App.vue

<template><div id="app"><div id="nav"><!-- 主应用--><router-link to="/home">app1</router-link>|<router-link to="/about">app1-about</router-link>|<router-link to="app2#x/home">app2</router-link>|<router-link to="app2#/about">app2-about</router-link><button @click="test">测试</button></div><router-view/><!-- 子应用容器--><div id="microApp"></div></div></template><script>exportdefault{
  methods:{test(){this.$router.push({path:"/app2/home"});}}}</script><style>
#app{
  font-family: Avenir, Helvetica, Arial, sans-serif;-webkit-font-smoothing: antialiased;-moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;}
 
#nav{
  padding:30px;}
 
#nav a{
  font-weight: bold;
  color: #2c3e50;}
 
#nav a.router-link-exact-active{
  color: #42b983;}</style>

src目录下新建views目录并新建about.vue和home.vue
about.vue

<!--/views/About.vue--><template><divclass="about"><h1>app1 about page</h1></div></template>

home.vue

<!--/views/Home.vue--><template><divclass="home"><h1>app1 home page test</h1></div></template>

src下新建router目录并新建index.js
index.js:

import VueRouterfrom'vue-router'import Vuefrom'vue'import Homefrom'@/views/home'import Aboutfrom'@/views/about'
Vue.use(VueRouter)const routes=[{ path:'/home', component: Home},{ path:'/about', component: About},// { path: '*', component: Hello },];const router=newVueRouter({
    mode:'history',// 通过环境变量来配置路由的 base url// base: process.env.VUE_APP_BASE_URL,
    routes});exportdefault router

package.json:

"scripts":{"serve":"vue-cli-service serve","serve:micro":"vue-cli-service serve --mode micro","build":"vue-cli-service build --mode buildMicro"},

app1项目改造完毕。

  1. 子应用app2应用改造
    main.js:
import Vuefrom'vue'import Appfrom'./App.vue'import routerfrom'./router'import singleSpaVuefrom'single-spa-vue'
Vue.config.productionTip=false/**
 * 子应用main.js
 */const appOptions={
  el:'#microApp',
  router,render:h=>h(App)}// if(window.singleSpaNavigate) {//   __webpack_public_path__="http://localhost:8082/"// }// 支持应用独立运行、部署,不依赖于基座应用if(!window.singleSpaNavigate){delete appOptions.elnewVue(appOptions).$mount('#app')}// 基于基座应用,导出生命周期函数const vueLifecycle=singleSpaVue({
  Vue,
  appOptions})exportfunctionbootstrap(){
  console.log('app2 bootstrap')return vueLifecycle.bootstrap(()=>{})}exportfunctionmount(){
  console.log('app2 mount')return vueLifecycle.mount(()=>{})}exportfunctionunmount(){
  console.log('app2 unmount')return vueLifecycle.unmount(()=>{})}

vue.config.js

constpackage=require('./package.json')
module.exports={// 告诉子应用在这个地址加载静态资源,否则会去基座应用的域名下加载
  publicPath:'//localhost:8082',// 开发服务器
  devServer:{
    port:8082},
  configureWebpack:{// 导出umd格式的包,在全局对象上挂载属性package.name,基座应用需要通过这个全局对象获取一些信息,比如子应用导出的生命周期函数
    output:{// library的值在所有子应用中需要唯一
      library:package.name,
      libraryTarget:'umd'}}}

App.vue:

<template><!-- 子应用--><div id="vue"><!--<div>"Welcome to Your Vue.js App"</div>--><router-view/></div></template>
  1. src下新建views目录并新建about.vue和home.vue
    about.vue
<!--/views/About.vue--><template><divclass="about"><h1>app2 about page</h1></div></template>

home.vue

<!--/views/Home.vue--><template><divclass="home"><h1>app2 home page</h1></div></template>

src目录下新建router目录并新建index.js
index.js

import VueRouterfrom'vue-router'import Vuefrom'vue'import Homefrom'@/views/home'import Aboutfrom'@/views/about';import Hellofrom'@/components/HelloWorld';
Vue.use(VueRouter)/**
 * 子应用路由
 */const routes=[{ path:'/home', component: Home},{ path:'/about', component: About},{ path:'*', component: Hello}// {//     path: '/about',//     component: () => import(/* webpackChunkName: "about" */'../views/about.vue'),//     meta: {//       keepAlive: true//     }// },];const router=newVueRouter({// mode: 'history',// 通过环境变量来配置路由的 base url// base: process.env.VUE_APP_BASE_URL,
    routes});exportdefault router

package.json下改造script属性值

"scripts":{"serve":"vue-cli-service serve","serve:micro":"vue-cli-service serve --mode micro","build":"vue-cli-service build --mode buildMicro"},

app2改成完成!

开始运行

1、在app1目录执行cmd命令:

npm run serve

执行结果:

 DONE  Compiled successfullyin 12673ms                                                                            下午5:05:14

  App running at:
  - Local:   http://localhost:8081/ 
  - Network: http://192.168.43.189:8081/

  Note that the development build is not optimized.
  To create a production build, runyarn build.

2、在app2目录执行cmd命令:

npm run serve

执行结果:

 DONE  Compiled successfullyin 9440ms                                                                                   下午5:05:53

  App running at:
  - Local:   http://localhost:8082/
  - Network: http://192.168.43.189:8082/

  Note that the development build is not optimized.
  To create a production build, runyarn build.

打开浏览器输入

http://localhost:8081/

结束

运行完成后,你刷新非主页面路由会直接404,请看我的下一篇博客
页面刷新404问题


引入ElementUi继续改造demo:
vue+single-spa+ElementUi项目demo

出现了npm依赖没有安装的问题,根据提示自行安装

  • 作者:上刀山
  • 原文链接:https://blog.csdn.net/shaoqi_123/article/details/121291163
    更新时间:2022-08-11 14:49:40