• 手把手教会你微前端开发(vue-qiankun)


    什么是微前端

    引用qiankun里的解释
    在这里插入图片描述
    简而言之,微前端就是可以将多个模块或者多个项目合并到一个项目中。a项目里可以嵌入b项目的页面,并且可以交互通信。

    为什么不用iframe

    在这里插入图片描述
    为了解决微服务架构, 后来出现了single-spa,但是也存在一切弊端。为此,蚂蚁金融科技孵化qiankun 基于微前端架构的云产品统一接入平台。

    qiankun

    官网地址:https://qiankun.umijs.org/zh
    Github 主页:https://github.com/umijs/qiankun

    注:qiankun暂时不支持vite

    qiankun 主要特性
    1、基于 single-spa 封装,提供了更加开箱即用的 API。
    2、技术栈无关,任意技术栈的应用均可 使用/接入,不论是React/Vue/Angular/JQuery 还是其他等框架。
    3、HTML Entry 接入方式,让我们接入微应用像使用 iframe 一样简单。
    4、样式隔离,确保微应用之间样式互相不干扰。
    5、JS 沙箱,确保微应用之间 全局变量/事件 不冲突。
    6、资源预加载,在浏览器空闲时间预加载未打开的微应用资源,加速微应用打开速度。
    7、umi 插件,提供了 @umijs/plugin-qiankun 供 umi 应用一键切换成微前端架构系统。

    qiankun-vue

    在此介绍vue微服务架构,首先创建三个项目
    basc ----主应用
    demo1 ---- 微应用
    demo2 ---- 微应用
    在basc主应用中嵌套demo1和demo2两个微应用
    在这里插入图片描述
    使用vue create basc,vue create demo1,vue create demo2自行创建,并下载模块qiankun

    npm i qiankun -S
    
    • 1

    主应用开发–basc

    1、主应用需要提供一个容器 DOM,用于插入加载的微应用。这里我们将 App.vue 修改成如下内容:()

    <template>
      <div id="app">
        <div id="nav">
          <router-link to="/app1">App1</router-link> |
          <router-link to="/app2">App2</router-link>
        </div>
        <div id="container"/>
      </div>
    </template>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    注:

    是微应用挂载的dom元素

    2、然后在 main.js 中注册微应用并 start 即可。

    提示:当微应用信息注册完之后,一旦浏览器的 url 发生变化,便会自动触发 qiankun 的匹配逻辑,所有 activeRule 规则匹配上的微应用就会被插入到指定的 container 中,同时依次调用微应用暴露出的生命周期钩子。

    import Vue from 'vue'
    import App from './App.vue'
    import router from './router'
    import store from './store'
     
    Vue.config.productionTip = false
     
    new Vue({
      router,
      store,
      render: h => h(App)
    }).$mount('#app')
     
    // 引入 qiankun 组件
    import { registerMicroApps, start } from 'qiankun';
     
    // 注册微应用信息
    registerMicroApps([
      {
        name: 'hangge-app-1',
        entry: 'http://localhost:9091',
        container: '#container',
        activeRule: '/app1',
      },
      {
        name: 'hangge-app-2',
        entry: 'http://localhost:9092',
        container: '#container',
        activeRule: '/app2',
      }
    ]);
    // 启动 qiankun
    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

    当然微应用也不是必须要跟路由关联,我也可以选择手动加载微应用的方式:

    import { loadMicroApp } from 'qiankun';
     
    loadMicroApp({
      name: 'hangge-app-1',
      entry: 'http://localhost:9091',
      container: '#container',
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    微应用开发–demo1/demo2

    1、首先在微应用的 src 目录下新增 public-path.js 文件,内容如下:

    if (window.__POWERED_BY_QIANKUN__) {
      __webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
    }
    
    • 1
    • 2
    • 3

    2、接着修改 main.js 文件,在最顶部引入 public-path.js,导出 bootstrap、mount、unmount 三个生命周期钩子,以供主应用在适当的时机调用。

    import './public-path';
    import Vue from 'vue'
    import App from './App.vue'
    import router from './router'
    import store from './store'
     
    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 只会在微应用初始化的时候调用一次,下次微应用重新进入时会直接调用 mount 钩子,不会再重复触发
     * 通常我们可以在这里做一些全局变量的初始化,比如不会在 unmount 阶段被销毁的应用级别的缓存等。
     */
    export async function bootstrap() {
      console.log('[vue] vue app bootstraped');
    }
     
    /**
     * 应用每次进入都会调用 mount 方法,通常我们在这里触发应用的渲染方法
     */
    export async function mount(props) {
      console.log('[vue] props from main framework', props);
      render(props);
    }
     
    /**
     * 应用每次 切出/卸载 会调用的方法,通常在这里我们会卸载微应用的应用实例
     */
    export async function unmount() {
      instance.$destroy();
      instance.$el.innerHTML = '';
      instance = null;
      router = 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
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50

    3、修改 router/index.js,设置路由 base,值和该微应用在主应用那边的 activeRule 是一样的。

    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: '/about',
        name: 'About',
        component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
      }
    ]
     
    const router = new VueRouter({
      mode: 'history',
      base: window.__POWERED_BY_QIANKUN__ ? '/app1/' : process.env.BASE_URL,
      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
    • 23
    • 24
    • 25
    • 26

    4、最后编辑项目根目录下的 vue.config.js 文件(如果没有则手动创建一个),修改 webpack 打包,允许开发环境跨域和 umd 打包。

    const { name } = require('./package');
    module.exports = {
      devServer: {
        headers: {
          'Access-Control-Allow-Origin': '*', //允许开发环境跨域
        },
      },
      configureWebpack: {
        output: {
          library: `${name}-[name]`,
          libraryTarget: 'umd', // 把微应用打包成 umd 库格式
          jsonpFunction: `webpackJsonp_${name}`,
        },
      },
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    5、经过上面修改后访问可能会报“error ‘webpack_public_path’ is not defined”错误。这个是 eslint 的问题,webpack_public_path 不是全局变量所导致的。我们在 package.json 文件中 eslintConfig 配置全局变量后重起服务即可解决。
    在这里插入图片描述
    6、vue.config.js修改后可能会出现报错
    在这里插入图片描述
    这是应为webpack版本的问题。webpack4不会出现这种问题。出现这个问题是因为webpack5的原因。webpack5将jsonpFunction更名为chunkLoadingGlobal
    所以webpack5的vue.config.js配置将jsonpFunction改为chunkLoadingGlobal就不会报错了

    const { name } = require("./package");
    module.exports = {
      devServer: {
        headers: {
          "Access-Control-Allow-Origin": "*", //允许开发环境跨域
        },
      },
      configureWebpack: {
        output: {
          library: `${name}-[name]`,
          libraryTarget: "umd", // 把微应用打包成 umd 库格式
          chunkLoadingGlobal: `webpackJsonp_${name}`,
        },
      },
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
  • 相关阅读:
    [附源码]Python计算机毕业设计SSM泸定中学宿舍管理系统设计(程序+LW)
    Spring Boot中配置多个数据源
    30岁生日收到公司的生日礼物,一份裁员通知,有人从此一蹶不振,而我逆风翻盘,重获新生~
    uni-app--》基于小程序开发的电商平台项目实战(七)完结篇
    智能电表上的模块发热正常吗?
    51单片机DHT11温湿度控制系统仿真设计( proteus仿真+程序+原理图+报告+讲解视频)
    docker部署的jenkins配置(接口自动化)
    数据结构——时间复杂度&空间复杂度
    如何打造一支专业的QA团队,至少要关注这5点
    《SpringCloud Alibaba》实战
  • 原文地址:https://blog.csdn.net/weixin_51499232/article/details/126298406