single-spa配置指南

295 阅读1分钟

子应用:

第一步:npm i single-spa-vue

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
})

/*  如果是父应用引入,文件的路径要改变
    window.singleSpaNavigate为true表示父应用引用了我
    保证子应用当前的引用路径都是绝对路径,相对于自己的路径,而不是父类的。
*/

if (window.singleSpaNavigate) {
  // eslint-disable-next-line no-undef
  __webpack_public_path__ = 'http://localhost:10000/'
}

// 希望子应用独立运行

// 独立运行时不能再挂载到#vue上了,要挂载到id为app的标签中
if (!window.singleSpaNavigate) {
  delete appOptions.el
  // eslint-disable-next-line no-new
  new Vue(appOptions).$mount('#app')
}
// 协议接入,父应用会调用这些方法
export const bootstrap = vueLifeCycle.bootstrap
export const mount = vueLifeCycle.mount
export const unmount = vueLifeCycle.unmount
vue.config.js
module.exports = {
  configureWebpack: {
    output: {
      // 向window中注册singleVue
      library: 'singleVue',
      // eslint-disable-next-line no-dupe-keys
      // 打包后的文件输出为umd格式
      libraryTarget: 'umd'
    },
    devServer: {
      port: 10000
    }
  }
}
router.js

为了正常显示,子应用中要虚拟一个路径,可以通过更改router的base属性,此时子应用在启动时会自动的以/vue为基准加载。

new VueRouter({
  mode: 'history',
  base: '/vue',
  routes
})

父应用

第一步:npm i single-spa

main.js
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'

import { registerApplication, start } from 'single-spa'

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

// 先注册一个应用,当条件满足时会加载另外一个应用的包(手动通过创建script标签去加载),加载好了以后子应用打包出来时会有bootStarp mount unmout供父应用调用
// 调mount方法时会走子应用的注册vue方法(appOptions),将子应用挂载到父应用的vue标签内

registerApplication(
  'myVueApp',
  async () => {
    await loadScript('http://localhost:10000/js/chunk-vendors.js')
    await loadScript('http://localhost:10000/js/app.js')
    return window.singleVue // bootStarp mount unmout
  },
  // 应用切换到/vue的路径下,需要加载刚定义的子应用
  location => location.pathname.startsWith('/vue')
  // 可以通过props进行父子通信
  // props: {}
)

start()

// customElements事件可以进行父子应用的通信

Vue.config.productionTip = false

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

新建一个id为vue的div,让子应用挂载

<template>
  <div id="app">
    <router-link to="/vue">加载vue应用</router-link>
    <!-- 子应用加载的位置 -->
    <div id="vue"></div>
  </div>
</template>

缺陷:

不够灵活,不能动态加载js文件

样式未隔离 没有js沙盒的机制