Skip to content

二.qiankun(用法解析)

qiankun 官网

1.创建项目

在 micro 文件夹下创建 3 个项目

bash
├── micro
     ├── base        # 作为微前端的基座(vue3.x技术栈)
     ├── sub1        # 作为微前端的子项目sub1(vue3.x技术栈)
     ├── sub2        # 作为微前端的子项目sub2(react17.x技术栈)

2.配置基座

配置入口文件

js
// src/main.js
import { createApp } from "vue"
import App from "./App.vue"
import router from "./router"
import store from "./store"
import ElementPlus from "element-plus"
import "element-plus/dist/index.css"
import { registerMicroApps, start } from "qiankun"
import microApps from "./micro-app"

const app = createApp(App)
app.use(ElementPlus)
app.use(store).use(router).mount("#app")

const config = {
  // 挂载前回调
  beforeLoad: [
    (app) => {
      console.log("beforeload", app)
    },
  ],
  // 挂载后回调
  beforeMount: [
    (app) => {
      console.log("beforeMount", app)
    },
  ],
  // 卸载后回调
  afterUnmount: [
    (app) => {
      console.log("afterMount", app)
    },
  ],
}

registerMicroApps(microApps(ElementPlus), config)
start({
  prefetch: false,
})

配置子项目

js
// src/micro-app.js
const microApps = [
  {
    name: "sub1",
    entry: "http://localhost:5501",
    activeRule: "sub1",
    container: "#sub1",
    props: {
      data: "来自基座的数据1",
      fns: [
        function LOGOUT_(data) {
          alert("父应用返回信息:" + data)
        },
      ],
    },
  },
  {
    name: "sub2",
    entry: "http://localhost:5052",
    activeRule: "sub2",
    container: "#sub2",
    props: {
      data: "来自基座的数据2",
      fns: [
        function LOGOUT_(data) {
          alert("父应用返回信息:" + data)
        },
      ],
    },
  },
]
const apps = (ui) =>
  microApps.map((item) => {
    item.props.ui = ui
    return {
      ...item,
      // props: {
      //   routerBase: item.activeRule,
      // },
    }
  })
export default apps

配置路由

js
// src/router/index.js
import { createRouter, createWebHistory } from "vue-router"
import Home from "../views/Home.vue"

const routes = [
  {
    path: "/",
    redirect: "/base",
  },
  {
    path: "/base",
    name: "Home",
    component: Home,
  },
  {
    path: "/base/about",
    name: "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: "about" */ "../views/About.vue"),
  },
]

const router = createRouter({
  base: "/base",
  history: createWebHistory(),
  routes,
})

export default router

3.配置 sub1

配置入口文件

js
// src/main.js
import { createApp } from "vue"
import App from "./App.vue"
import router from "./router"
import store from "./store"

let app = null

function render(props = {}) {
  const { container } = props
  console.log(container)
  app = createApp(App)
  app.use(store)
  app.use(router)
  app.mount("#vue")
}
if (window.__POWERED_BY_QIANKUN__) {
  window.__webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__
  console.log("1111111111", window.__webpack_public_path__)
} else {
  console.log("2222222222")
  render()
}

export async function bootstrap(props) {
  console.log(props)
}
export async function mount(props) {
  render(props)
  app.use(props.ui)
  // props.fns.forEach(fn => fn('加载完成'))
}
export async function unmount() {
  app.unmount()
  console.log(app, "app")
}

配置路由

js
// src/router/index.js
import { createRouter, createWebHistory } from "vue-router"
import Home from "../views/Home.vue"
import About from "../views/About.vue"

const routes = [
  {
    path: "/",
    redirect: "/sub1/about1",
  },
  {
    path: "/sub1",
    name: "Home",
    component: Home,
  },
  {
    path: "/sub1/about1",
    name: "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: About,
  },
]

const router = createRouter({
  base: "/sub1",
  history: createWebHistory(),
  routes,
})

export default router

配置 webpack

js
// vue.config.js
module.exports = {
  devServer: {
    port: 5501,
    headers: {
      "Access-Control-Allow-Origin": "*",
    },
  },
  configureWebpack: {
    output: {
      library: "sub1",
      libraryTarget: "umd",
    },
  },
}

4.配置 sub2

配置入口文件

js
// src/index.js
import React from "react"
import ReactDOM from "react-dom"
import "./index.css"
import App from "./App"
import reportWebVitals from "./reportWebVitals"

reportWebVitals()

function render(props = {}) {
  const { container } = props
  console.log(container)
  ReactDOM.render(
    <React.StrictMode>
      <App />
    </React.StrictMode>,
    document.getElementById("root")
  )
}
if (window.__POWERED_BY_QIANKUN__) {
  window.__webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__
  console.log("1111111111", window.__webpack_public_path__)
} else {
  console.log("2222222222")
  render()
}

export async function bootstrap(props) {
  console.log(props)
}
export async function mount(props) {
  render(props)
  // props.fns.forEach(fn => fn('加载完成'))
}
export async function unmount() {
  ReactDOM.unmountComponentAtNode(document.getElementById("root"))
}

配置 webpack

js
// config-overrides.js
module.exports = {
  webpack: (config) => {
    config.output.library = `sub2`
    config.output.libraryTarget = "umd"
    config.output.publicPath = "http://localhost:5052/"
    return config
  },
  devServer: function (configFunction) {
    return function (proxy, allowedHost) {
      const config = configFunction(proxy, allowedHost)
      config.headers = {
        "Access-Control-Allow-Origin": "*",
      }
      return config
    }
  },
}

5.效果