• vite+vue3+ts项目搭建之集成qiankun让其成为子应用模板(vite+vue3+ts+qiankun项目)


    前言

    以下操作,是续接之前 第四步 ——即:vite+vue3+ts+pinia+element-plus项目已完成搭建好,可以直接业务开发了
    主应用技术栈:vue2+webpack+js

    集成qiankun(微前端)

    1、安装vite-plugin-qiankun

    npm install vite-plugin-qiankun
    
    • 1

    2、vite.config.ts文件修改,代码如下:

    import qiankun from 'vite-plugin-qiankun'
    const packName = require('./package').name  // 必须要指定当前子应用命名
     // 配置NG——这个是与后台、运维约定好的,做NG转发;即主应用地址+子应用base就会直接NG转发
      base: '/vitedemo',
     plugins: [
      // 配置qiankun
        qiankun(`${packName}`, {
          useDevMode: true
        }),
        ...
     ]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    注意点:
    本地启动测试主子应用切换需要在server:{}里面添加headers: {‘Access-Control-Allow-Origin’: ‘*’ }, 解决主应用跳子应用跨域问题

    server: {
        headers: {
          'Access-Control-Allow-Origin': '*'
        },
        host: '0.0.0.0',
        port,
        open: true,
        https: false,
        ...
       }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    2、main.ts文件修改,完整代码如下:

    import { createApp } from 'vue'
    import App from './App.vue'
    import router from './router'
    // 所有业务api接口
    import api from './api'
    /**
     * element-plus
     */
    import ElementPlus from 'element-plus'
    import 'element-plus/dist/index.css'
    // 因element-plus默认是英文,我们指定一下默认中文
    import locale from 'element-plus/lib/locale/lang/zh-cn'
    // 图标并进行全局注册
    import * as ElementPlusIconsVue from '@element-plus/icons-vue'
    // pinia代替vuex
    import pinia from './store'
    // 权限控制(全局路由守卫)
    import './permission'
    /**
     * 样式
     */
    // 公共样式
    import '@/assets/styles/index.scss'
    // 初始化样式
    import 'normalize.css'
    // 统一注册 baseComponents
    import baseComponentsInstall from '@/components/baseComponents/install'
    // svg渲染
    import SvgIcon from '@/components/SvgIcon/index.vue'
    /**
     * 配置qiankun
     */
    import { renderWithQiankun, qiankunWindow } from 'vite-plugin-qiankun/dist/helper'
    let instance: any = null
    function render(props: any = {}) {
      const { container } = props
      instance = createApp(App)
      instance.use(router)
      instance.use(pinia)
      // 注册全局api方法
      instance.config.globalProperties.$api = api
      // 注册所有图标
      for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
        instance.component(key, component)
      }
      // 注册ElementPlus
      instance.use(ElementPlus, {
        locale // 语言设置
        // size: Cookies.get('size') || 'medium' // 尺寸设置
      })
      // 自动注册全部本地组件
      instance.use(baseComponentsInstall)
      // 全局组件祖册
      instance.component(
        'SvgIcon',
        // 如果这个组件选项是通过 `export default` 导出的,那么就会优先使用 `.default`,否则回退到使用模块的根
        SvgIcon.default || SvgIcon
      )
      instance?.mount(container ? container.querySelector('#app') : '#app')
      console.log('开始加载相关内容')
    }
    renderWithQiankun({
      mount(props: any) {
        render(props)
      },
      bootstrap() {
        console.log('%c', 'color:green;', ' ChildOne bootstrap')
      },
      update() {
        console.log('%c', 'color:green;', ' ChildOne update')
      },
      unmount(props: any) {
        console.log('unmount', props)
        instance.unmount()
        instance._container.innerHTML = ''
        instance = null
      }
    })
    if (!qiankunWindow.__POWERED_BY_QIANKUN__) {
      console.log('并不是qiankun渲染')
      render()
    }
    
    • 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
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82

    3、router.ts文件修改,完整代码如下:

    import { createRouter, createWebHistory } from 'vue-router'
    import { qiankunWindow } from 'vite-plugin-qiankun/dist/helper'
    import Layout from '@/layout/index.vue'
    import login from '@/views/login.vue'
    export const constantRoutes: any = qiankunWindow.__POWERED_BY_QIANKUN__
      ? [
        {
          path: '/login',
          name: 'login',
          component: login,
          hidden: true,
          meta: {
            rootPage: true,
            noCache: true
          }
        },
        {
          path: '/redirect',
          component: Layout,
          hidden: true,
          children: [
            {
              path: '/redirect/:path(.*)',
              component: () => import('@/views/redirect.vue')
            }
          ]
        },
        {
          path: '',
          component: Layout,
          redirect: 'index',
          hidden: true,
          children: [
            {
              path: '/index',
              component: () => import('@/views/index.vue'),
              name: 'index',
              hidden: true,
              meta: { title: '首页', icon: 'monitor', noCache: true, affix: true }
            }
          ]
        }
      ]
      : [
        {
          path: '/redirect',
          component: Layout,
          hidden: true,
          children: [
            {
              path: '/redirect/:path(.*)',
              component: () => import('@/views/redirect.vue')
            }
          ]
        },
        {
          path: '/login',
          component: login,
          hidden: true,
          meta: {
            noCache: true
          }
        },
        {
          path: '/404',
          component: () => import('@/views/error/404.vue'),
          hidden: true
        },
        {
          path: '/401',
          component: () => import('@/views/error/401.vue'),
          hidden: true
        },
        {
          path: '',
          component: Layout,
          redirect: 'index',
          hidden: true,
          children: [
            {
              path: '/index',
              component: () => import('@/views/index.vue'),
              name: 'index',
              hidden: true,
              meta: { title: '首页', icon: 'monitor', noCache: true, affix: true }
            }
          ]
        }
      ]
    
    const router = createRouter({
      history: createWebHistory(qiankunWindow.__POWERED_BY_QIANKUN__ ? '/' : '/vitedemo/'),
      routes: constantRoutes,
    })
    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
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95

    3、全局路由守卫permission.ts文件修改,完整代码如下:

    import router from './router'
    import NProgress from 'nprogress'
    import 'nprogress/nprogress.css'
    import { getToken } from '@/utils/cookies'
    import { ElMessage } from 'element-plus'
    import { qiankunWindow } from 'vite-plugin-qiankun/dist/helper'
    import useUserStore from '@/store/modules/user'
    import usePermissionStore from '@/store/modules/permission'
    NProgress.configure({ showSpinner: false })
    const whiteList = ['/login']
    router.beforeEach((to: any, from: any, next: Function) => {
      NProgress.start()
      if (getToken()) {
        if (to.path === '/login') {
          next({ path: '/' })
          NProgress.done()
        } else {
          if (usePermissionStore().sysMenu.length === 0) {
            // 路由信息是不是组装完
            useUserStore().GetInfo()
            usePermissionStore().generateRoutes()
              .then((accessRoutes: any) => {
                accessRoutes.forEach((rout: any) => {
                  router.addRoute(rout) // 动态添加可访问路由表
                })
                next({ ...to, replace: true })
              })
              .catch(err => {
                useUserStore().FedLogOut()
                  ElMessage.error(err.message || err.msg || '出现错误,请稍后再试')
                  next({ path: '/' })
              })
          } else {
            // 进入页面前设置菜单
            if (!qiankunWindow.__POWERED_BY_QIANKUN__) {
              // 子应用单独运行,直接进入该系统
              const add_routes = toRaw(usePermissionStore().sysMenu)
              if (to.path === '/index') {
                let lastChild =
                  add_routes[0]?.children?.length > 0
                    ? add_routes[0].children[0]
                    : add_routes[0]
                if (to.path === lastChild.path) return false
                next(lastChild)
                NProgress.done()
              } else {
                console.log('子项目的next')
                next()
              }
            } else {
              console.log('主应用进入')
              next()
            }
          }
        }
      } else {
        if (whiteList.indexOf(to.path) !== -1) {
          next()
        } else {
          next(`/login`)
          NProgress.done()
        }
      }
    })
    router.afterEach(() => {
      NProgress.done()
    })
    
    
    • 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
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68

    4、其他文件修改,如下:

    在这里插入图片描述

    5、到此子应用已经配置完成

    在这里插入图片描述

    主应用跳转到子应用

    主应用技术栈: vue2+js+element-ui

    1、main.js修改,代码如下:

    因为子应用是接口获取的,无需在单个注册

    import { registerMicroApps, start } from "qiankun";
    // 获取所有子应用
    import childrenApp from './children.json'
    // console.log('clientType=B', res)
    const res = childrenApp
    if (res.code == 200) {
      if (window.__POWERED_BY_QIANKUN__) {
        __webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
      }
      console.log('获取所有子应用', res.data)
      const apps = res.data.children && res.data.children.map((item) => {
        return {
          name: item.packageName,// 微应用package.json的name字段
          entry: item.entry,// 微应用访问地址,默认加载这个html页面并解析其中的js动态执行
          container: '#app', // 容器名
          activeRule: item.activeRule,// 激活路径,微应用路由
        }
      })
      apps && registerMicroApps(apps, {
        beforeLoad: async (app) => {
          console.log('before load', app)
          document.title = 'vue3+vite+ts'
        },
        beforeMount: [async (app) => {
          console.log('before mount', app.name)
        }]
      })
      // 启动 qiankun
      start()
    } else {
      Element.Message.warning('加载微应用失败,将无法访问子系统')
    }
    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
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    2、最终效果

    在这里插入图片描述

    新增主应用在线地址

    可以在线切换进入wocwin-vue2(常规vue2+webpack后台管理系统模板)、wocwin-admin(常规vue3+vite+Ts后台管理系统模板)

    组件地址

    主应用在线地址

    gitHub组件地址

    gitee码云组件地址

    主子应用切换demo源码地址

    相关文章

    基于ElementUi再次封装基础组件文档


    vue3+ts基于Element-plus再次封装基础组件文档

  • 相关阅读:
    【Hello Go】Go语言运算符
    【Git】Git常用命令
    【刷题专栏—突破思维】LeetCode 138. 随机链表的复制
    notion, followus, wolai, wiz, lark
    go语言中的锁底层分析(二)
    【Python】SimpleITK使用笔记
    Spring Boot(六十六):集成Alibaba Druid 连接池
    nodeJs 基础
    Java--Lambda(1)简介
    gitlab 简单优化 gitlab cpu高,内存高 gitlab 负载飙高
  • 原文地址:https://blog.csdn.net/cwin8951/article/details/127431084