微前端之single-spa

single-spa

  • 前言
  • single-spa是啥
  • single-spa实战
  • 总结

前言

其实早就想写一篇关于微前端实践的文章了,几个月之前就看过有关微前端的视频,也查过一些文档,但是好像没有总结,现在又忘记一些了,今天实操了一遍,这里就总结一下,正好实习公司工作小组项目采用的就是微前端。今天先讲解一下single-spa,后面在讲解qiankun。

插曲:今天本来跟着别人一起敲代码,但是发现使用vue-cli脚手架创建项目老是报错,error403。昨天我在公司是可以使用的,通过npm是可以下载包的,但是今天打开电脑就发现报错。找了很多博客,解决一下几个问题:
一:(不记得截屏去了,尴尬)使用vue-cli 创建项目时报错,大致是说,npm 中的插件存在版本问题,后面通过修改./vuer中的配置为true,就可以使用脚手架创建项目。
二:今天在安装single-spa-vue这个包时,包error403,查了一些文章,都说是npm publish的问题,可是我这都没发布包了,怎么可能,后面详细解读错误,找到一个npm 镜像 是公司内部的源,这一下就知道是啥意思了,我Mac没有安装VPN连接公司的内网,所以造成了这一些问题,还有一个就是npm源的问题,可以切换到淘宝源
三:好久没有使用react 了,今天发现create-react-app 版本升级了,之前的不进行维护了,版本为4.0.3,小伙伴记得跟新。

single-spa是啥

single-spa是微前端解决方案的一种解决措施,single-spa由国外大佬发明。single-spa主要步骤是,在主应用中注册所有可能加载的微应用,微应用的声明必须在入口函数中暴露出三个钩子函数(bootstrap,mount,unmount),提供三个函数给主应用使用,bootstrap为启动准备,mount为挂载,unmount为销毁。主应用通过发送请求加载子应用打包好的lib库,然后执行子应用的lib就行。

single-spa实战

1,首先创建一个主应用(可以是vue,react,其他)和子应用

vue create parent-vue  //我这里采用了vue
vue create child-vue

2,安装single-spa

// 在主应用中加载single-spa
npm i single-spa --save
// 在子应用中加载single-spa-vue或者single-spa-react
npm i single-spa-vue --save

3,配置主应用的环境,并注册子应用

import Vue from 'vue'
import App from './App.vue'
import router from './router'
// 在主应用中引入single-sap
import { registerApplication,start } from "single-spa";


Vue.config.productionTip = false

// 声明一个函数,用来加载打包好的库
async function loadScript (url) {
  return new Promise((resolve,reject)=>{
    console.log('go')
    let script = document.createElement('script');
    script.src = url;
    // 加载成功执行成功回调
    script.onload = resolve;
    script.onerror = reject;
    document.head.appendChild(script);
  })
}

// 进行注册
registerApplication('childVue',
async () => {
  console.log('jiazai ')
  // 在这里加载子应用打包出来的 app.js chunk-vendors.js 两个类库,注意加载循序
  await loadScript(`http://localhost:10010/js/chunk-vendors.js`);
  await loadScript(`http://localhost:10010/js/app.js`)

  //加载子应用打包的lib之后,window上面挂载子应用对象,对象中包含钩子函数,将其返回出去
  return window.singleVue

},
location => location.pathname.startsWith('/vue')
)

// 启动主应用
start();



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


注意:由于主应用与子应用之间存在跨域问题,所以主应用请求加载子应用的时候得进行跨域处理,上面代码使用jsonp,script标签自带跨域功能。

4,配置子应用

import Vue from 'vue'
import App from './App.vue'
import router from './router'
// 引入single-spa-vue微服务插件
import singleSpaVue from "single-spa-vue";

Vue.config.productionTip = false

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

// 生成配置对象
const appOptions = {
  el: '#vue',
  router,
  render: h => h(App)
}

// 子引用必须向外暴露三个钩子函数

const singleLifeCycle = new singleSpaVue({
  Vue,
  appOptions // 将配置对象传过去
})

// 这里劫持主应用来请求子应用的路由,由于主应用的域名和子应用不同,所以这里劫持,修改域名
if(window.singleSpaNavigate){
  __webpack_public_path__ = 'http://localhost:10010/'
}

// 如果主应用没有请求子应用,单独请求子应用,注意挂载点
if(!window.singleSpaNavigate){
  delete appOptions.el;
  new Vue(appOptions).$mount('#app')
}


// 实例对象上有所需暴露的三个钩子函数
 export const bootStrap = singleLifeCycle.bootstrap;
 export const mount = singleLifeCycle.mount;
 export const unmount = singleLifeCycle.unmount;



注意:配置子应用的时候,按照single-spa协议必须得暴露三个钩子函数。

5,配置子应用打包成为lib

// 在配置中,将子应用打包成lib,给父引用调用
module.exports = {
    configureWebpack:{
        output:{
            library:'singleVue',
            libraryTarget:'umd'
        },
        devServer:{
            port:10010
        }
    }

}

// umd 格式,会将打包好的lib文件挂载到,引用的Window属性上
// 所以父应用可以通过window.bootstrap,window.mount...

在根目录创建一个vue.config.js文件,配置打包。library是打包后的应用名,libraryTarget是打包后的格式。(这里是vue子应用配置)

6,子应用路由配置


// 由于是在主应用上跳转路由,所以这里得在主应用路由基础上 去跳转
const router = new VueRouter({
  mode: 'history',
  base: '/vue',
  routes
})

子应用打包后的文件
微前端之single-spa_第1张图片
app.js
微前端之single-spa_第2张图片
chunk-vendors.js
微前端之single-spa_第3张图片
注意:主应用请求的时候,必须得先请求基础配置包chunk-vendors.js然后才是请求app.js。

总结

其实single-spa文件实现是不难的,从上面看也就几行代码,主要是理解思路,代码是其次,路由跳转路径尤其得注意。

single-spa的缺点:
1,从上面的运行结果可以看出,主应用加载子应用会出现样式冲突,样式污染。
2,js也会存在同样的污染问题(主:window.a 子:window.a 当子应用挂载到主应用时,会出现问题)
3,主应用必须得手动加载子应用打包好的lib库文件,如果子应用比较多,比较麻烦。

你可能感兴趣的:(前端)