• qiankun - 微前端应用搭建


    qiankun 是一个基于 single-spa微前端实现库,旨在帮助大家能更简单、无痛的构建一个生产可用微前端架构系统。

    主应用

    1. 创建项目(我这里使用的vue2)
    // @vue/cli 5.0.4
    vue create main-app
    
    • 1
    • 2
    1. 安装 qiankun
    yarn add qiankun
    
    • 1
    1. 注册微应用

    新增文件夹micros,文件夹下新增 app.js

    // src/micros/app.js
    // 微应用信息
    const apps = [
      {
        name: 'vue-app', // 微应用的名称,微应用之间必须确保唯一
        entry: '//localhost:8081/', // 微应用的入口,运行地址
        container: '#micro-container', // 微应用的容器节点
        activeRule: '/vue-app' // 微应用的激活规则
      }, {
        name: 'react-app'
        entry: '//localhost:8082/',
        container: '#micro-container',
        activeRule: '/react-app'
      }
    ]
    
    export default apps
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    micros 下新增 index.js

    // src/micros/index.js
    import { addGlobalUncaughtErrorHandler, registerMicroApps, start } from 'qiankun'
    // 微应用的信息
    import apps from './app'
    
    /**
     * registerMicroApps(apps, lifeCycles?)
     * apps: 必选,微应用的一些注册信息
     * lifeCycles: 可选,全局的微应用生命周期钩子
     */
    registerMicroApps(apps, {
      // qiankun 生命周期钩子 - 微应用加载前
      beforeLoad: (app) => {
        console.log('before load=====', app.name)
        return Promise.resolve()
      },
      // qiankun 生命周期钩子 - 微应用挂载后
      afterMount: (app) => {
        console.log('after mount=====', app.name)
        return Promise.resolve()
      }
    })
    
    // 添加全局的未捕获异常处理器
    addGlobalUncaughtErrorHandler((event) => {
      console.error(event)
      const { message: msg } = event
      if (msg && msg.includes('died in status LOADING_SOURCE_CODE')) {
        console.error('微应用加载失败,请检查应用是否可运行')
      }
    })
    
    export default start
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    main.js 中启动

    // src/main.js
    import Vue from 'vue'
    import App from './App.vue'
    import router from './router'
    import store from './store'
    import start from './micros'
    
    start()
    Vue.config.productionTip = false
    
    new Vue({
      router,
      store,
      render: h => h(App)
    }).$mount('#app')
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    1. 页面及路由(这里使用的history模式)
    <template>
      <div id="app">
        <nav class="menu">
          <router-link to="/">Homerouter-link>
          <router-link to="/vue-app">vue-approuter-link>
          <router-link to="/react-app">react-approuter-link>
        nav>
        <div class="main">
          <router-view>router-view>
          
          <div id="micro-container">div>
        div>
      div>
    template>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    // src/router/index.js
    import Vue from 'vue'
    import VueRouter from 'vue-router'
    
    Vue.use(VueRouter)
    
    const routes = [
      {
        path: '/',
        name: 'home',
        component: () => import(/* webpackChunkName: "home" */ '@/views/home.vue')
      }
    ]
    
    const router = new VueRouter({
      mode: 'history',
      routes
    })
    
    export default router
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    微应用

    vue-app微应用

    1. 创建项目
    vue create vue-app
    
    • 1
    1. src下新增 public-path.js
    // src/public-path.js
    if (window.__POWERED_BY_QIANKUN__) {
      __webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
    }
    
    • 1
    • 2
    • 3
    • 4
    1. 路由文件修改(这里使用的history模式)
    // src/router/index.js
    import Vue from 'vue'
    import VueRouter from 'vue-router'
    
    Vue.use(VueRouter)
    
    const routes = [
      {
        path: '/',
        name: 'home',
        component: () => import(/* webpackChunkName: "home" */ '../views/home.vue')
      }
    ]
    
    const router = new VueRouter({
      mode: 'history',
      // base设置,与主应用activeRule规则一致
      base: window.__POWERED_BY_QIANKUN__ ? '/vue-app' : '/',
      routes
    })
    
    export default router
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    1. main.js文件修改
    // src/main.js
    import Vue from 'vue'
    import App from './App.vue'
    import router from './router'
    import store from './store'
    import './public-path'
    
    Vue.config.productionTip = false
    let instance = null
    function render (props = {}) {
      const { container } = props
      instance = new Vue({
        router,
        store,
        render: (h) => h(App)
      }).$mount(container ? container.querySelector('#app') : '#app')
    }
    // 独立运行时
    if (!window.__POWERED_BY_QIANKUN__) {
      render()
    }
    
    // 微应用生命周期
    // bootstrap 初始化
    export async function bootstrap () {
      console.log('vue-app bootstraped')
    }
    // mount 挂载
    export async function mount (props) {
      console.log('vue-app mount', props)
      render(props)
    }
    // unmount 卸载
    export async function unmount () {
      console.log('vue-app unmount')
      instance.$destroy()
      instance.$el.innerHTML = ''
      instance = null
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    1. vue.config.js 文件修改
    // 这里的 name 应为 'vue-app' 与注册名一致
    const { name } = require('./package')
    
    module.exports = {
      devServer: {
        port: 8081,
        historyApiFallback: true,
        allowedHosts: 'all',
        headers: {
          'Access-Control-Allow-Origin': '*'
        }
      },
      configureWebpack: {
        output: {
          library: name,
          // // 把微应用打包成 umd 库格式
          libraryTarget: 'umd',
          chunkLoadingGlobal: `webpackJsonp_${name}`
        }
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    现在就可以访问到微应用vue-app了
    在这里插入图片描述

    react-app微应用

    1. 创建项目
    // create-react-app 5.0.1
    create-react-app react-app
    
    • 1
    • 2
    1. src下新增public-path.js
    // src/public-path.js
    if (window.__POWERED_BY_QIANKUN__) {
      __webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
    }
    
    • 1
    • 2
    • 3
    • 4
    1. App.js修改
    // src/App.js
    import { Routes, Route, BrowserRouter as Router} from 'react-router-dom'
    import './App.css'
    import Home from './components/Home'
    
    function App() {
      return (
        <div className="App">
          {/* base设置,与主应用activeRule规则一致 */}
          <Router basename={window.__POWERED_BY_QIANKUN__ ? '/react-app' : '/'}>
            <Routes>
              <Route path="/" element={<Home />} />
            </Routes>
          </Router>
        </div>
      )
    }
    
    export default App
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    1. index.js修改
    // src/index.js
    import React from 'react'
    import { createRoot } from 'react-dom/client' // react18
    import App from './App'
    import reportWebVitals from './reportWebVitals'
    import './public-path'
    
    let instance = null
    
    function render(props) {
      const { container } = props
      const root = createRoot(container ? container.querySelector('#root') : document.querySelector('#root'))
      root.render(<App />)
      instance = root
    }
    
    if (!window.__POWERED_BY_QIANKUN__) {
      render({})
    }
    
    export async function bootstrap() {
      console.log('react-app bootstraped')
    }
    
    export async function mount(props) {
      console.log('react-app mount', props)
      render(props)
    }
    
    export async function unmount(props) {
      console.log('react-app unmount')
      instance.unmount()
      instance = null
    }
    
    reportWebVitals()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    1. 修改webpack配置

    安装插件 react-app-rewired,当然也可以选择其他的插件,例如 @rescripts/cli

    yarn add react-app-rewired -D
    
    • 1

    根目录新增config-overrides.js

    const path = require("path")
    const resolve = (dir) => path.join(__dirname, dir)
    // 这里的 name 应为 'react-app' 与注册名一致
    const { name } = require("./package")
    
    module.exports = {
      webpack: (config) => {
        config.output.library = name
        config.output.libraryTarget = 'umd'
        config.output.chunkLoadingGlobal = `webpackJsonp_${name}`
        config.output.globalObject = 'window'
    
        config.resolve.alias = {
          ...config.resolve.alias,
          '@': resolve('src')
        }
        return config
      },
    
      devServer: function (configFunction) {
        return function (proxy, allowedHost) {
          const config = configFunction(proxy, allowedHost)
          config.allowedHosts = 'all'
          config.headers = {
            'Access-Control-Allow-Origin': '*',
          }
          config.historyApiFallback = true
    
          return config
        }
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    修改package.json

    "scripts": {
        "start": "react-app-rewired start",
        "build": "react-app-rewired build",
        "test": "react-app-rewired test",
        "eject": "react-app-rewired eject"
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    现在就可以访问到微应用react-app了
    在这里插入图片描述

  • 相关阅读:
    前端登录加密解密方法
    一套 .NET开发的邮箱Mail开源库
    第3章 Tomcat&servlet
    智能穿戴领域,健康鞋步力宝品牌引领新商业模式发展
    倍福触摸屏维修倍福显示屏维修CP3916-0000故障概述
    AI视频教程下载:用ChatGPT自动化各种工作任务
    表空间的空间管理算法
    Numpy 从零快速入门教程
    Linux系统安全:安全技术和防火墙
    Oracel存储过程,分页函数定义,索引建立
  • 原文地址:https://blog.csdn.net/z291493823/article/details/125891986