路由

import Vue from "vue";
import VueRouter from "vue-router";
import Home from "../views/Home.vue";
 
Vue.use(VueRouter);
 
const routes = [
  {
    path: "/",
    name: "Home",
    component: Home,
  },
  {
    path: "*",
    name: "sub~about",
    // route level code-splitting
    // this generates a separate chunk (about.[hash].js) for this route
    // which is lazy-loaded when the route is visited.
    component: () =>
      import(/* webpackChunkName: "single-host" */ "@/views/SingleHost.vue"),
  },
];
 
const router = new VueRouter({
  routes,
});
 
export default router;
 

容器页面载体

<template>
  <div ref="host" />
</template>
 
<script>
import "systemjs/dist/system";
import "systemjs/dist/extras/use-default";
import {
  start,
  getAppStatus,
  getAppNames,
  registerApplication,
  unregisterApplication,
  triggerAppChange,
} from "single-spa/lib/esm/single-spa.dev.js";
 
export default {
  name: "SingleHost",
  watch: {
    $route(to, from) {
      if (to.fullPath !== from.fullPath) {
        triggerAppChange();
      }
    },
  },
 
  mounted() {
    const apps = [
      {
        name: "sub1",
        // publicPath: "http://127.0.0.1:8080/subs/sub1/",
        publicPath: "http://127.0.0.1:8889/",
      },
      {
        name: "sub2",
        // publicPath: "http://127.0.0.1:8080/subs/sub1/",
        publicPath: "http://127.0.0.1:8080/",
      },
    ];
    // 先根据路由找到最可能的子应用,然后加载+注册
    const pre = apps.find((v) => location.hash.indexOf(v.name) > -1);
    console.log("fetch", pre);
    this.loadManifest(pre)
      .then(start)
      .finally(() => {
        console.log("prefetch all");
        Promise.all(apps.map((app) => this.loadManifest(app))).finally(start);
      });
  },
 
  beforeDestroy() {
    Promise.all(getAppNames().map((app) => unregisterApplication(app)));
  },
 
  methods: {
    async loadManifest(app) {
      return app && !getAppStatus(app.name)
        ? window.System.import(`${app.publicPath}/manifest.json`).then(
            ({ default: data }) => {
              const { assets } = data.entrypoints.app;
              registerApplication(
                app.name,
                () => this.loadChildAppJs(app.publicPath, assets),
                (location) => location.hash.startsWith(`#/${app.name}`),
                {
                  domElement: this.$refs.host,
                }
              );
            }
          )
        : Promise.resolve(true);
    },
    async loadChildAppJs(publicPath, assets) {
      let appUrl;
      try {
        const jsPath = assets.filter((v) => v.endsWith(".js")).pop();
        appUrl = publicPath + jsPath;
      } catch (e) {
        console.log(e);
      }
      console.log("loading", appUrl);
      return window.System.import(appUrl);
    },
  },
};
</script>