微前端之 qiankun 入门、上手、实战(构建大型 web 应用)

news2024/11/20 3:29:33

目录

前言

正文

一、介绍

微前端

qiankun

二、快速上手

​☛主应用

① 安装 qiankun

② 在主应用中注册微应用

​☛微应用 

① 导出相应的生命周期钩子

② 配置微应用的打包工具

三、项目实战

​☛主应用 

① 安装 qiankun

② 注册微应用并启动

③ 主应用添加路由

​☛微应用

① 新增 public-path.js

② 建议使用 history 模式

③ 引入 public-path.js

④ 修改 webpack

✔整合效果

四、扩展

修改主应用路由模式

修改注册微应用配置

为微应用添加路由

写在最后


前言

随着技术栈越来越广泛,许多前端框架也层出不穷,使得我们在构建 web 应用时,由于技术栈之间的差异,难以协同开发。而目前其中一个主流方案就是使用微前端,让不同技术栈、框架能独立开发,独立部署子模块,再共同嵌入主模块,形成一个完整的大型 web 应用。微前端是一种多个团队通过独立发布功能的方式来共同构建现代化 web 应用的技术手段及方法策略。

本文主要介绍微前端实现方案之一:qiankun

正文

一、介绍

微前端

微前端是一种多个团队通过独立发布功能的方式来共同构建现代化 web 应用的技术手段及方法策略。

微前端架构具备以下几个核心价值:

  • 技术栈无关
    主框架不限制接入应用的技术栈,微应用具备完全自主权

  • 独立开发、独立部署
    微应用仓库独立,前后端可独立开发,部署完成后主框架自动完成同步更新

  • 增量升级

    在面对各种复杂场景时,我们通常很难对一个已经存在的系统做全量的技术栈升级或重构,而微前端是一种非常好的实施渐进式重构的手段和策略

  • 独立运行时
    每个微应用之间状态隔离,运行时状态不共享

微前端架构旨在解决单体应用在一个相对长的时间跨度下,由于参与的人员、团队的增多、变迁,从一个普通应用演变成一个巨石应用(Frontend Monolith)后,随之而来的应用不可维护的问题。这类问题在企业级 Web 应用中尤其常见。

qiankun

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

qiankun 孵化自蚂蚁金融科技基于微前端架构的云产品统一接入平台,在经过一批线上应用的充分检验及打磨后,我们将其微前端内核抽取出来并开源,希望能同时帮助社区有类似需求的系统更方便的构建自己的微前端系统,同时也希望通过社区的帮助将 qiankun 打磨的更加成熟完善。

目前 qiankun 已在蚂蚁内部服务了超过 2000+ 线上应用,在易用性及完备性上,绝对是值得信赖的。

qiankun 的核心理念:

  •  简单

    由于主应用微应用都能做到技术栈无关,qiankun 对于用户而言只是一个类似 jQuery 的库,你需要调用几个 qiankun 的 API 即可完成应用的微前端改造。同时由于 qiankun 的 HTML entry 及沙箱的设计,使得微应用的接入像使用 iframe 一样简单。

  • 解耦/技术栈无关

    微前端的核心目标是将巨石应用拆解成若干可以自治的松耦合微应用,而 qiankun 的诸多设计均是秉持这一原则,如 HTML entry、沙箱、应用间通信等。这样才能确保微应用真正具备 独立开发、独立运行 的能力。

特性:

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

二、快速上手

主应用

① 安装 qiankun

$ npm i qiankun -S  # 或者 yarn add qiankun

② 在主应用中注册微应用

import { registerMicroApps, start } from 'qiankun';

registerMicroApps([
  {
    name: 'vue-app',
    entry: '//localhost:8080',
    container: '#container',
    activeRule: '/activeRule',
  },
]);

start();

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

微应用 

微应用不需要额外安装任何其他依赖即可接入 qiankun 主应用。

① 导出相应的生命周期钩子

微应用需要在自己的入口 js (通常就是你配置的 webpack 的 entry js) 导出 bootstrapmountunmount 三个生命周期钩子,以供主应用在适当的时机调用。

/**
 * bootstrap 只会在微应用初始化的时候调用一次,下次微应用重新进入时会直接调用 mount 钩子,不会再重复触发 bootstrap。
 * 通常我们可以在这里做一些全局变量的初始化,比如不会在 unmount 阶段被销毁的应用级别的缓存等。
 */
export async function bootstrap() {
  console.log('app bootstraped');
}

/**
 * 应用每次进入都会调用 mount 方法,通常我们在这里触发应用的渲染方法
 */
export async function mount(props) {
  // 渲染方法等
}

/**
 * 应用每次 切出/卸载 会调用的方法,通常在这里我们会卸载微应用的应用实例
 */
export async function unmount(props) {
  
}

/**
 * 可选生命周期钩子,仅使用 loadMicroApp 方式加载微应用时生效
 */
export async function update(props) {
  console.log('update props', props);
}

② 配置微应用的打包工具

除了代码中暴露出相应的生命周期钩子之外,为了让主应用能正确识别微应用暴露出来的一些信息,微应用的打包工具需要增加如下配置:

webpack:

const packageName = require('./package.json').name;

module.exports = {
  output: {
    library: `${packageName}-[name]`,
    libraryTarget: 'umd',
    jsonpFunction: `webpackJsonp_${packageName}`,
  },
};

三、项目实战

以下例子中我创建两个 vue2 项目,一个为主应用,一个为微应用(当然你也可以使用其他框架)。话不多说,直接实战!

主应用 

主应用不限技术栈,只需要提供一个容器 DOM,然后注册微应用并 start 即可。这里我的主应用是 vue2 项目,项目的搭建过程不在此赘述,直接进入 qiankun 使用阶段。

项目视图如下:

① 安装 qiankun

npm i qiankun -S

② 注册微应用并启动

为了结构清晰,我在 /src 下新建一个 micro 目录,里面新建一个文件 index.js

index.js

import { registerMicroApps, start } from 'qiankun';
// 注册微应用
registerMicroApps([
  {
    name: 'appVue2.7',   // 自定义微应用名称
    entry: '//localhost:8081/',   // 微应用的入口地址,即微应用运行起来的地址
    container: '#container',   // 挂载微应用内容的dom节点(此处为主应用的dom)
    activeRule: '/#/app-vue',  
    // 匹配微应用的路由前缀(/#/,主应用为hash模式,在url命中时,即加载对应的微应用)
  },
]);
// 启动 qiankun
start();

③ 主应用添加路由

由于我们在主应用使用了左侧菜单栏,且设置了路由展示,因此我们需要在主应用中配置微应用对应的路由 path,确保点击菜单栏能切换到对应的路由地址。

注意:在注册微应用前,确保我们的微应用启动正常。

此时我已经另外新建一个 vue2.7 的项目当成微应用(当然你也可以使用 react、angular 等框架)并且已经成功启动,地址为 localhost:8081(即主应用注册微应用配置中的 entry)。

微应用视图展示:

接下来就是微应用的配置。

微应用

微应用分为有 webpack 构建和无 webpack 构建项目,有 webpack 的微应用(主要是指 Vue、React、Angular)需要做的事情有:

① 新增 public-path.js

用于修改运行时的 publicPath。什么是运行时的 publicPath ?。

if (window.__POWERED_BY_QIANKUN__) {
  window.__webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}

注意:运行时的 publicPath 和构建时的 publicPath 是不同的,两者不能等价替代。

② 建议使用 history 模式

需要设置路由 base,值和它的 activeRule 是一样的。该例子微应用暂不使用路由(本文“扩展”部分添加路由使用部分,不容错过哟)。

③ 引入 public-path.js

修改并导出三个生命周期函数。

// main.js
import './public-path';   // 引入
import Vue from 'vue';
import App from './App.vue';

Vue.config.productionTip = false;

let instance = null;
function render(props = {}) {
  const { container } = props;
  instance = new Vue({
    render: (h) => h(App),
  }).$mount(container ? container.querySelector('#app') : '#app');
}

// 独立运行时
if (!window.__POWERED_BY_QIANKUN__) {
  render();
}

export async function bootstrap() {
  console.log('[vue] vue app bootstraped');
}
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;
}

④ 修改 webpack

允许开发环境跨域和 umd 打包。

// vue.config.js
const { defineConfig } = require('@vue/cli-service')
const { name } = require('./package');
module.exports = defineConfig({
  transpileDependencies: true,
  devServer: {
    headers: {
      'Access-Control-Allow-Origin': '*',
    },
  },
  configureWebpack: {
    output: {
      library: `${name}-[name]`,
      libraryTarget: 'umd', // 把微应用打包成 umd 库格式
      //jsonpFunction: `webpackJsonp_${name}`,
    },
  },
})

主要的修改就是以上四个,可能会根据项目的不同情况而改变。例如,你的项目是 index.html 和其他的所有文件分开部署的,说明你们已经将构建时的 publicPath 设置为了完整路径,则不用修改运行时的 publicPath (第一步操作可省)。

无 webpack 构建的微应用直接将 lifecycles 挂载到 window 上即可。

整合效果

在主应用、微应用都配置完毕之后,接下来就是见证奇迹的时刻了。

我们在主应用切换到微应用匹配的 url,即在注册微应用时

activeRule: '/#/app-vue',

我们在主应用切换菜单

此时地址为 ’/#/app-vue’(hash 模式),但是子应用却没展示出来。经过排查,我们发现在注册微应用时,我们配置了一个容器用于展示微应用

container: '#container',

但是在主应用中并没有找到对应容器,于是重新修改代码

此时刷新,微应用成功展示

主应用端口为 8080,微应用端口为 8081,且主应用顺利挂载微应用,微前端方案成功实现!

四、扩展

回过头来看,我们主应用路由使用的模式是 hash 模式,那么改成 history 模式又该如何修改?

其实很简单,只需要修改两处地方:

修改主应用路由模式

修改注册微应用配置

修改完毕,回到页面,查看效果,history 模式显示正常

为微应用添加路由

前面我们提到,微应用路由建议使用 history 模式,并设置路由 base,值和它的 activeRule 是一样的。

import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '@/components/HelloWorld'
import About from '@/components/About'
 
Vue.use(Router)
 
export default new Router({
  // 路由模式
  mode: 'history',
  // 本项目为微应用时,基础路径为 /app-vue,即与注册微应用时的 activeRule 一致
  base: window.__POWERED_BY_QIANKUN__ ? "/app-vue" : "/",
  routes: [
    {
      path:'/',
      redirect:'/home'
    },
    {
      path: '/home',
      name: 'HelloWorld',
      component: HelloWorld
    },
    {
      path: '/about',
      name: 'About',
      component: About
    }
  ]
})

在 mian.js 中注入路由

import './public-path';
import Vue from 'vue';
import App from './App.vue';
import router from './router';

Vue.config.productionTip = false;

let instance = null;
function render(props = {}) {
  const { container } = props;
  instance = new Vue({
    router,   // 添加此行,注入路由,其他配置不变
    render: (h) => h(App),
  }).$mount(container ? container.querySelector('#app') : '#app');
}

// 独立运行时
if (!window.__POWERED_BY_QIANKUN__) {
  render();
}

export async function bootstrap() {
  console.log('[vue] vue app bootstraped');
}
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;
}

到主应用查看效果

微应用中 Home、About 顺利切换与展示,路由添加成功。至此,一个基础的微前端 web 项目搭建起来了,我们可以在这个的基础上继续进行迭代与开发。微应用不限制技术栈与框架,多人协同开发大型web项目,简直YYDS!

更多细节请参考:qiankun - qiankun

写在最后

创作不易,如有帮助,请不要吝啬您的手指,一键三连点一波,感谢支持;如有不恰当之处,还请不吝赐教。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/409011.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ES6--》对象扩展方法

目录 对象扩展 name 属性 属性的遍历 super关键字 Object.is() Object.assign() Object.getOwnPropertyDescriptors() Object.setPrototypeOf() Object.getPrototypeOf() Object.keys()、Object.values、Object.entries()、Object.fromEntries() Object.hasOwn() 对…

如何在 2022 年为 Web 应用程序选择技术堆栈

文章目录什么是技术堆栈?为 Web 开发选择技术堆栈时要考虑的事项选择熟悉的技术跟随趋势考虑项目的细节确保高安全级别记住你的最后期限选择前端技术栈框架编程语言选择后端技术栈编程语言数据库技术堆栈是您应用程序的核心选择最佳的 Web 应用程序堆栈并非易事&…

vue3+ts遇到的小问题

插件volar安装了没有提示。 解决:1. 检查是或否是最新的版本,是的话进入拓展设置,所有的选项都勾选 2. 还是不行就要更新vscoe了。一般的话会在力捕抓到一个错误。跟新就好了 TypeScript intellisense is disabled on template. To enab…

【简陋Web应用2】人脸检测——基于Flask和PaddleHub

文章目录🚩 前言🌺 效果演示🥦 分析与设计🍉 实现🍬 1. 部署人脸检测模型🍭 2. 使用Flask构建app2.1 目录结构2.2 forms.py2.3 utils.py2.4 app.py2.5 index.html🥝 Bug(s)🚩 前言 本…

Vue根据网络文件路径下载文件【自定义属性 v-down】

Vue根据网络文件路径下载文件【v-down】标准使用方式企业级Vue开发集成(全局挂载)1.src目录下创建directive文件夹(存在则忽略)2.down.js文件3.directive根目录创建index.js文件4.main.js 注册自定义属性全局挂载提到下载文件大家首先肯定会想到 模拟点击…

vue2 使用 cesium 篇 【第一篇】

vue2 使用 cesium 篇 今天好好写一篇哈,之前写的半死不活的。首先说明:这篇博文是我边做边写的,小白也是,实现效果会同时发布截图,如果没有实现也会说明,仅仅作为技术积累,选择性分享&#xff0…

面试官:“ES6中新增的Set方法去重你会吗?”我:“看文章就知道了”

赶快悄悄的努力起来吧,不苒在这里衷心祝愿各位大佬都能顺利通过面试。 面试专栏分享,感觉有用的小伙伴可以点个订阅,不定时更新相关面试题:面试专栏 。 文章目录 Set 的基本使用🍔前言🍏正文1. Set1.1 Set的基本使用1.2 Set 常见的属相和方法1.3 应用场景:使用Set对数…

vue组件通信2 | 父子组件通信v-model

引言:最近项目在vue2 升级vue3 ,在这个过程中发现v-model 的变化最大。同时也发现了对于v-model 的不熟悉。 因此,本文从文档、vue2的使用方法、vue2 tsx 的使用方法、vue3的使用方法、使用场景来试图探究一下v-model。 一、文档及vue2中 v-…

vue页面刷新

vue页面刷新 首先我们都知道vue属于单页面应用,默认境况下是不会触发刷新页面操作的,所以这个时候就需要我们通过事件来触发reload()来达到刷新操作 接下来我就为大家介绍三种刷新页面的方法 1. wiindow.location.reload([bForceGet])该方法强迫浏览…

vue中组件的name属性含义与用法

vue中组件的name属性含义与用法 name属性:只有作为组件选项时起作用,用来注册组件名 1、注册组件名 局部注册组件,语法:export default{ components:{"组件名":组件对象}} 其中,"组件名"注册方…

从0搭建Vue3组件库(五): 如何使用Vite打包组件库

本篇文章将介绍如何使用 vite 打包我们的组件库,同时告诉大家如何使用插件让打包后的文件自动生成声明文件(*.d.ts) 打包配置 vite 专门提供了库模式的打包方式,配置其实非常简单,首先全局安装 vite 以及vitejs/plugin-vue pnpm add vite vitejs/plugin-vue -D -w 在 componen…

基于Vue+Nodejs实现宿舍管理系统

​ 作者主页:编程指南针简介:Java领域优质创作者、CSDN博客专家 Java项目、简历模板、学习资料、面试题库、技术互助文末获取源码​ 项目编号:BS-QD-002 主要需求: 学生信息录入、修改、删除、查询宿舍管理评分学生早起率、懒…

js之promise

##### 仅做记录复习使用 #### 数据有点混乱 暂时不要看 promise promise是一个对异步操作进行封装并返回其结果的构造函数. 使代码更加简洁和避免回调地狱。 promise是浏览器引擎自带的(但不是所有浏览器都支持promise) promise的参数是一个函数且…

全网详细解决Set-Location : 找不到接受实际参数“xxx”的位置形式参数。 所在位置 行:1 字符: 1的错误,并深究该错误的原因。

文章目录1. 复现错误2. 分析错误3. 解决问题4. 文末总结1. 复现错误 今天使用PowerShell从C:\Users\baoya>目录切换到C:\Program Files\MySQL\MySQL Server 5.7\bin时,却报出如下图的错误: 即找不到接受实际参数“Files\MySQL\MySQL”的位置形式参数。…

vue最易理解且详细的调用swiper插件

我们最开始接触的是在操作dom时候的时候引入swiper,那么这次我就用之前的文档来教你在vue中如何调用swiper. 我们之前看的是swiper教程 那么我根据上面的教程一步一步来教你使用 1.首先创建好swiper组件.写好template 里面的标签内容(当然这里写了个插槽为了以后方便动态插入…

【跨域】一篇文章彻底解决跨域设置cookie问题!

一篇文章彻底解决跨域设置cookie问题! 大家好我是雪人~~⛄ 之前做项目的时候发现后端传过来的 SetCookie 不能正常在浏览器中使用。 是因为谷歌浏览器新版本Chrome 80将Cookie的SameSite属性默认值由None变为Lax。 接下来带大家解决该问题。 原理讲解 我们可以看到…

Java - token的存储与获取

1. 获取token的工具类 问:为什么写工具类呢??? 答:因为我们不知道前端将token怎么存储的,所以我们可以通过调用Token工具类来获取token。Token工具类会检查header、URL中的属性值、以及Cookie等等&#xff…

快速生成Vue2或者vue3模板

1.点击文件,再点击首选项,然后选择用户片段; 2.在弹出来的输入框中,选择第一行vue.json或者第二行新建全局代码片段文件都可,都是为了打开vue.json文件; 3.把下面代码复制到vue.json文件里,然后…

vue3搭建教程(基于vite+create-vue+ element-plus)

前言2021年8月5日&#xff0c;Vue正式发布3.2版本&#xff0c;同时&#xff0c;Vue的作者尤雨溪还在个人微博称&#xff1a;“ < script setup > TS Volar 真香 ”&#xff1b;2022年1月22日&#xff0c;Vue官方宣布Vue3成为了新的默认版本。如今的Vue3已经势不可挡&a…

【JavaScript-进阶】详解数据类型,内存分配,API元素对象获取

目录 前言 1.数据类型 1.简单数据类型和复杂数据类型 2.堆和栈 2.webApi 1.API 2.DOM是啥&#xff1f; 3.如何获取元素&#xff1f; 1.根据ID获取 ​编辑 2.根据标签名获取 3.通过HTML5新增的方法获取 4.特殊元素获取(body,html) 总结 前言 祝大家中秋节快乐…