某马 qiankun 公开课 学习记录

news2024/11/15 8:00:27

端午早晨阳光正好,起来学习一小下 

客观评价一哈:此视频适合不了解 qiankun 的朋友入门观看,更详细的使用方法还是推荐 qiankun 官网哦,老师讲的生动活泼,值得萌新一听

某马 qiankun 公开课 - bilibili ovo很多公司的中后台项目已经在用微前端了,qiankun是目前比较完善的一种微前端解决方案。因此掌握如何使用qiankun去搭建微前端项目,不管是在面试还是在实际工作,都能为自己技术加分。本课程会带大家基于qiankun从零搭建微前端项目,并分享一些微前端中常见的难点,助力大家提升技术实力!, 视频播放量 6747、弹幕量 18、点赞数 107、投硬币枚数 48、收藏人数 602、转发人数 26, 视频作者 黑马前端, 作者简介 为您呈现前端精品技术干货,进阶学习、课程体验、就业指导,可联系播妞q:1905496411,相关视频:答应我,别再乱用微前端了!?,微前端qiankun快速入门,前阿里P8前端大神 winter | 带你系统构建前端体系,前端死不死? 我不知道,反正我的热爱快耗尽了,黑马程序员前端微信小程序开发教程,微信小程序从基础到发布全流程_企业级商城实战(含uni-app项目多端部署),React入门到实战(2022全网最新),基于qiankun+vue-element-admin微前端改造【源码下载】,微前端singlespa教程,qiankun教程,00后应届生|大厂技术岗的一天,使用@umijs/plugin-qiankun搭建微前端应用合辑https://www.bilibili.com/video/BV12T411q7dq/?spm_id_from=333.880.my_history.page.click&vd_source=8bc01635b95dbe8ecd349b2c23b03a10qiankun 官网https://qiankun.umijs.org/zh/guide

 

目录

1.什么是微前端

2.微前端的好处

3.现有的微前端方案

3.1 iframe

3.2 single-spa

3.3 qiankun

4.基于 qiankun 的微前端实战

4.1 基座改造

4.1.1 安装 qiankun

4.1.2 修改入口文件

4.2 React 微应用改造

4.2.1 修改微应用入口文件

4.2.2 新增 public-path.js

4.2.3 修改 webpack 配置

4.3 Vue 微应用改造

4.3.1 使用 Vite 创建微应用

4.3.2 安装 vite-plugin-qiankun 依赖,修改 vite.config.js

4.3.3 修改微应用入口文件

4.4 umi 脚手架创建的 React 项目改造

4.4.1 安装 umijs/plugins 插件

4.4.2 配置 .umirc.ts

4.4.3 修改微应用入口文件

5. 常见需求的实现

5.1 样式隔离

5.2 微应用之间的跳转

hash(推荐)

history

5.3 公共依赖加载

5.4 全局状态管理


1.什么是微前端

微前端可以简单理解为:将一个大应用拆分成多个子应用,每个子应用由不同团队管理,并可以自主选择框架,独立部署上线

微前端多应用于 中后台项目,因为企业内部 中后台项目 存活时间较长,动辄三五年或者更多,最后演变成巨石应用的概率,高于其他 WEB 应用。导致了了 技术栈落后、编译部署慢 等问题

2.微前端的好处

3.现有的微前端方案

3.1 iframe

iframe 具有天然的隔离属性,每个子应用通过 iframe 标签嵌入到父应用中,各个子应用之间、子应用和父应用之间 互不影响

但是 iframe 也有局限性:

  • URL 不同步,如果刷新页面,iframe 嵌入的子应用路由会丢失(比如我嵌入了 vue 官网,点击了某个章节,路由变化了,刷新之后,路由丢失,又回到了 vue 官网首页)
  • 全局上下文完全隔离,内存变量不共享
  • UI 不同步(比如 iframe 嵌入的子应用,如果有带遮罩层的弹窗组件,则遮罩就不能覆盖整个浏览器,只能在 iframe 区域中生效)
  • 响应速度慢,每次进入子应用的过程,都是一次浏览器上下文重建、资源重新加载的过程

3.2 single-spa

single-spa 官网https://zh-hans.single-spa.js.org/docs/getting-started-overview

single-spa 是最早的微前端框架,可以兼容很多技术栈

single-spa 首先在基座中,注册所有子应用的路由,当 URL 改变时就会去进行匹配,匹配到子应用就会去加载对应的子应用(qiankun 就是基于这个思路实现的)

相对于 iframe 的实现方案,single-spa 中基座和各个子应用之间,共享着一个全局上下文,并且不存在 URL 不同步、UI 不同步的情况

但是 single-spa 也有局限性:

  • 没有实现 js 隔离、css 隔离
  • 需要修改大量的配置,包括基座和子应用的,不能开箱即用

3.3 qiankun

qiankun 是阿里开源项目,在内部经过很多上线应用的检验了,可以放心使用~

qiankun 有什么优势呢?

  • 基于 single-spa 封装,提供了 开箱即用 的 API
  • 实现了 single-spa 不具备的 js 隔离、css 隔离
  • 技术栈无关,任意技术栈的应用均可使用 / 接入,不论是 React/Vue/Angular/JQuery 还是其他框架 / 库
  • HTML Entry 的方式接入,像使用 iframe 一样简单(就是在基座的 html 中,通过 script link 等方式引入 子应用 的 umd 包)
  • 资源预加载,在浏览器空闲时,预加载未启动的微应用资源,加速微应用启动速度

4.基于 qiankun 的微前端实战

项目结构:

  • 基座应用(主应用):负责集成所有的子应用,提供微应用入口,尽量不写复杂的业务逻辑
  • 微应用(子应用):根据不同业务划分,每个微应用都打包成 umd 模块,供基座应用加载
├── micro-base // 基座
├── sub-react // react 子应用,create-react-app 创建的应用,使用 webpack 打包
├── sub-vue // vue 子应用,vite 创建的应用,使用 vite 打包
└── sub-umi // umi 脚手架创建的子应用

4.1 基座改造

基座是用 create-react-app 脚手架 + antd 组件库搭建的项目,也可以选择 Vue 或其他框架,一般来说,基座只提供加载微应用的容器,尽量不写复杂的业务逻辑

4.1.1 安装 qiankun

// 安装 qiankun
npm i qiankun
yarn add qiankun

4.1.2 修改入口文件

// 在src/index.tsx 中,增加如下代码
import { start, registerMicroApps } from 'qiankun';

// 1. 要加载的子应用列表
const apps = [
  {
    name: "sub-react", // 子应用的名称
    entry: '//localhost:8080', // 默认会加载这个路径下的 html,解析里面的 js
    activeRule: "/sub-react", // 匹配的路由
    container: "#sub-app" // 加载的容器
  },
]

// 2. 注册子应用
registerMicroApps(apps, {
  beforeLoad: [async app => console.log('before load', app.name)],
  beforeMount: [async app => console.log('before mount', app.name)],
  afterMount: [async app => console.log('after mount', app.name)],
})

// 3. 启动 qiankun
start()

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

方法介绍: 

  • registerMicroApps(apps, lifeCycles?) —— 注册所有子应用,qiankun 会根据 activeRule 去匹配对应的子应用并加载
  • start(options?) —— 启动 qiankun,可以进行预加载和沙箱设置

至此基座就改造完成,其他框架的项目改造步骤类似

4.2 React 微应用改造

使用 create-react-app 脚手架创建微应用,为了不暴露所有的 webpack 配置,选择用 react-app-rewired 工具来改造 webpack 配置

4.2.1 修改微应用入口文件

添加 render 方法,在 qiankun 环境下,使用 基座应用 指定的 container 容器挂载微应用,否则使用 微应用自身的 root 容器挂载微应用

判断是否在qiankun 环境下,非 qiankun 环境下独立运行,传入 {},qiankun 环境下非独立运行,传入 props

增加生命周期要 export 否则可能报错

  • bootstrap —— 只会在微应用初始化的时候调用一次,下次微应用重新进入时会直接调用 mount 钩子,不会再重复触发 bootstrap
  • mount —— 应用每次进入都会调用 mount 方法,通常我们在这里触发应用的渲染方法 render
  • unmount —— 应用每次 切出/卸载 会调用的方法,通常在这里我们会卸载微应用的应用实例
let root: Root

// 将 render 方法用函数包裹,供后续主应用与独立运行调用
function render(props: any) {
  const { container } = props
  const dom = container ? container.querySelector('#root') : document.getElementById('root')
  root = createRoot(dom)
  root.render(
    <BrowserRouter basename='/sub-react'>
      <App/>
    </BrowserRouter>
  )
}

// 判断是否在 qiankun 环境下,非 qiankun 环境下独立运行
if (!(window as any).__POWERED_BY_QIANKUN__) {
  render({});
}

// 各个生命周期
// bootstrap 只会在微应用初始化的时候调用一次,下次微应用重新进入时会直接调用 mount 钩子,不会再重复触发 bootstrap。
export async function bootstrap() {
  console.log('react app bootstraped');
}

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

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

4.2.2 新增 public-path.js

if (window.__POWERED_BY_QIANKUN__) {
  // 动态设置 webpack publicPath,防止资源加载出错
  // eslint-disable-next-line no-undef
  __webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__
}

4.2.3 修改 webpack 配置

// 在根目录下新增 config-overrides.js 文件,并新增如下配置
const { name } = require("./package");

module.exports = {
  webpack: (config) => {
    config.output.library = `${name}-[name]`;
    config.output.libraryTarget = "umd";
    config.output.chunkLoadingGlobal = `webpackJsonp_${name}`;
    return config;
  }
};

4.3 Vue 微应用改造

4.3.1 使用 Vite 创建微应用

npm create vite@latest

4.3.2 安装 vite-plugin-qiankun 依赖,修改 vite.config.js

npm i vite-plugin-qiankun # yarn add vite-plugin-qiankun

import qiankun from 'vite-plugin-qiankun';

export default defineConfig({
    base: '/sub-vue', // 和基座中配置的 activeRule 一致
    server: {
      port: 3002,
      cors: true,
      origin: 'http://localhost:3002'
    },
    plugins: [
      vue(),
      qiankun('sub-vue', { // 配置 qiankun 插件
        useDevMode: true
      })
    ]
})

注意事项:

  • 一定要 export default 配置,不然会报错
  • 配置 base 意味着使用 history 路由,容易产生问题,比如微应用内跳转另一个微应用,会出现路由错误,所以推荐 hash 路由

4.3.3 修改微应用入口文件

import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
import { renderWithQiankun, qiankunWindow } from 'vite-plugin-qiankun/dist/helper';

let app: any;
if (!qiankunWindow.__POWERED_BY_QIANKUN__) {
  createApp(App).mount('#app');
} else {
  renderWithQiankun({
    // 子应用挂载
    mount(props) {
      app = createApp(App);
      app.mount(props.container.querySelector('#app'));
    },
    // 只有子应用第一次加载会触发
    bootstrap() {
      console.log('vue app bootstrap');
    },
    // 更新
    update() {
      console.log('vue app update');
    },
    // 卸载
    unmount() {
      console.log('vue app unmount');
      app?.unmount();
    }
  });
}

4.4 umi 脚手架创建的 React 项目改造

4.4.1 安装 umijs/plugins 插件

npm i @umijs/plugins

4.4.2 配置 .umirc.ts

export default {
  base: '/sub-umi',
  npmClient: 'npm',
  plugins: ['@umijs/plugins/dist/qiankun'],
  qiankun: {
    slave: {},
  }
};

4.4.3 修改微应用入口文件

完成上面两步,就可以在基座应用中,看到 umi 子应用的加载了

如果想在 qiankun 的生命周期中做些处理,需要继续修改入口文件

export const qiankun = {
  async mount(props: any) {
    console.log(props)
  },
  async bootstrap() {
    console.log('umi app bootstraped');
  },
  async afterMount(props: any) {
    console.log('umi app afterMount', props);
  },
};

5. 常见需求的实现

5.1 样式隔离

qiankun 实现了各个微应用之间的样式隔离,但是基座和应用之间的样式隔离没有实现,所以基座和微应用之间的样式,还会有冲突和覆盖的可能

比如基座使用了 antd 组件库修饰 link 链接样式,那么这套样式在微应用中也会生效

解决方法:

  • 每个应用的样式使用固定的格式
  • 通过 css-module 的方式给每个应用自动加上前缀

5.2 微应用之间的跳转

举个例子:

  • 假设 A 微应用路由为 /a/xxx,B微应用路由为 /b/xxx
  • 我想在 A 微应用里加个链接,直接跳转到 B 微应用
  • 实际点击后,路由变成了 /a/b/xxx,跳转失败

如何解决这个问题呢?

hash(推荐)

基座应用 + 微应用都是 hash 模式,基座应用根据 hash 来判断微应用,则不存在这种问题,因为 #a/xxx 会被直接替换成 #b/xxx

history

history 模式下微应用之间的跳转,或者微应用跳主应用页面,直接使用 微应用的路由实例 是不行的,这是因为路由使用了 history 模式,微应用的路由实例跳转都基于路由的 base 

有两种办法可以跳转:

  • history.pushState()
  • 将主应用的路由实例通过 props 传给微应用,微应用这个路由实例跳转

具体方案:在基座中复写并监听 history.pushState() 方法并做相应的跳转逻辑

// 重写函数
const _wr = function (type: string) {
  const orig = (window as any).history[type]
  return function () {
    const rv = orig.apply(this, arguments)
    const e: any = new Event(type)
    e.arguments = arguments
    window.dispatchEvent(e)
    return rv
  }
}

window.history.pushState = _wr('pushState')

// 在这个函数中做跳转后的逻辑
const bindHistory = () => {
  const currentPath = window.location.pathname;
  setSelectedPath(
  	routes.find(item => currentPath.includes(item.key))?.key || ''
  )
}

// 绑定事件
window.addEventListener('pushState', bindHistory)

5.3 公共依赖加载

举个例子:如果 主应用 和 子应用 使用了相同的库或者包(比如 antd, axios 等),可以用 externals 的方式来引入,减少加载重复包导致的资源浪费

方式:

  • 主应用:将所有公共依赖配置在 webpack 的 externals 选项中,并且在 index.html 使用外链引入这些公共依赖
  • 子应用:和主应用一样配置,注意:还需要给子应用的公共依赖的加上  ignore 属性(这是自定义的属性,非标准属性),qiankun 在解析时如果发现 ignore 属性,就会自动忽略

以 axios 为例:

<!-- 注意:这里的公共依赖的版本必须一致 -->
<script ignore="true" src="https://unpkg.com/axios@1.1.2/dist/axios.min.js"></script>
// 修改config-overrides.js
const { override, addWebpackExternals } = require('customize-cra')

module.exports = override(
  addWebpackExternals ({
    axios: "axios",
  }),
)

5.4 全局状态管理

 一般来说,各个子应用是通过业务来划分的,不同业务线应该降低耦合度,尽量去避免通信,但是如果涉及到一些公共的状态或者操作,qiankun 也是支持的

qinkun 提供了一个全局的 GlobalState 来共享数据,基座初始化之后,微应用可以监听到这个数据的变化,也能修改这个数据

基座

// 基座初始化
import { initGlobalState } from 'qiankun';

const state = { count: 1 };
const actions = initGlobalState(state);

// 主项目项目监听和修改
actions.onGlobalStateChange((state, prev) => {
  // state: 变更后的状态; prev 变更前的状态
  console.log(state, prev);
});

actions.setGlobalState(state);

微应用

// 子项目监听和修改
export function mount(props) {

  props.onGlobalStateChange((state, prev) => {
    // state: 变更后的状态; prev 变更前的状态
    console.log(state, prev);
  });

  const state = { count: 2 };
  props.setGlobalState(state);

  render(props)
}

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

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

相关文章

高通Camera Log Debug 知识点

和你一起终身学习&#xff0c;这里是程序员Android 经典好文推荐&#xff0c;通过阅读本文&#xff0c;您将收获以下知识点: 一、Camx UMD Log Debug二、Camx KMD log Debug三、常用缩写解释四、参考文献 一、Camx UMD Log Debug 1.1 两种方式设置camx UMD Log /vendor/etc/cam…

GPT-3.5眼中的编程语言之最:Python的卓越之处

当谈论编程语言的选择时&#xff0c;每个开发者都有自己的偏好和理由。作为GPT-3.5&#xff0c;以我的分析和学习能力&#xff0c;我也有自己心目中的编程语言之最。在众多编程语言中&#xff0c;Python在我的眼中独树一帜&#xff0c;是最令人着迷和受欢迎的编程语言之一。 首…

面试经典150题(1)

文章目录 前言除自身以外数组的乘积要求思路代码 跳跃游戏|要求题解代码 跳跃游戏||要求题解代码 前言 今天开始我将陆续为大家更新面试经典150题中较难理解的题目。今天我为大家分享的是&#xff0c;除自身以外数组的乘积、跳跃游戏| 和 跳跃游戏||。 除自身以外数组的乘积 …

【unity之UiI专题】GUI(IMGUI)详解

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;元宇宙-秩沅 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 秩沅 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a;uni…

AI 绘画工具 Stable Diffusion 本地安装使用

最近要用到 AI 绘画&#xff0c;所以研究了下目前市面上的 AI 绘画工具&#xff0c;真可谓是琳琅满目&#xff0c;但主流的还是 Stable diffusion 和 Midjourney 两大阵营。 Midjourney 不多说&#xff0c;开箱即用&#xff0c;对新手非常友好&#xff0c;但不免费&#xff0c…

Linux基础(二)—— 怎么在VMware/WSL中安装Ubuntu系统

文章目录 01 | VMware安装Ubuntu02 | WSL2安装Ubuntu 虚拟机安装Linux的方式分为两种&#xff1a;APP安装、WSL安装 APP安装就是常见的VMware VirtualBox安装的方式&#xff0c;而WSL是Windows系统自带的一个虚拟机应用&#xff0c;可以更好的与Windows进行信息交互&#xff08…

判断是否为美丽数组

判断是否为美丽数组c思路和实现 这段代码的功能是对于给定的多个序列&#xff0c;判断每个序列是否是一个 beautiful 序列。没次读取当前的序列判断之后再加入下一个数字进序列。 首先&#xff0c;输入一个整数 t&#xff0c;表示测试数据组数。 对于每组测试数据&#xff0c;…

【初识C语言】字符串+转义字符+注释

文章目录 1. 字符串2. 转义字符转义字符表常见转义字符 3. 注释 1. 字符串 “hello world.\n” 上面这种由双引号引起的一串字符就被称为字符串&#xff1b; 字符串的存储 C 语言当中没有字符串类型&#xff0c;如果想要将字符串存储起来的话就需要用到字符串数组。 #include…

Excel VBA 编程入门

Visual Basic for Applications&#xff08;VBA&#xff09;是一种用于 Microsoft Office 套件中的编程语言&#xff0c;它可以帮助您自动化重复性任务、定制应用程序以及增强工作效率。本文将向您介绍 Excel VBA 编程的基础知识&#xff0c;并通过示例帮助您入门。 1、启用“开…

融云WICC2023:成为「卷王」的路上,如何更好借力 AIGC

近期&#xff0c;“融云 WICC2023 泛娱乐出海嘉年华”在广州成功举办&#xff0c;行业多方力量与数百位开发者汇聚一堂&#xff0c;共同探讨出海人布局全球的突围之道。关注【融云全球互联网通信云】了解更多 在嘉年华的圆桌会议环节&#xff0c;白鲸出海创始人&#xff06;CE…

Axure教程—计数器

本文将教大家如何用AXURE制作计数器&#xff08;商品购件数的交互设计&#xff09; 一、效果 预览地址&#xff1a;https://uf9ie1.axshare.com 二、功能 1、用户点击“”号时数值加1 2、用户点击“-”号时数值减1 三、制作 数值 拖入一个矩形组件&#xff0c;其大小设置为164…

个人一年工作情况总结报告

个人一年工作情况总结报告篇1 转眼间又到了年终岁尾&#xff0c;这一年就要在很充实忙碌的工作中过去了。在这一年里&#xff0c;我收获了很多也积累了不少的工作经验。同时在两位领导和各位主管的帮助与支持下&#xff0c;我很好的完成了本职工作。作为一名办公室文员&#xf…

云计算成本大揭秘:硬件、研发、电力等各项成本都在这里!

‍数据智能产业创新服务媒体 ——聚焦数智 改变商业 云计算作为一种技术和商业模式&#xff0c;已经深深地影响了全球的IT行业和各种商业运营。云服务商的主要模式以订阅为基础&#xff0c;一旦应用程序和工作负载移动到云上&#xff0c;它们通常会停留在那里&#xff0c;订阅…

js blob 文件上传

js blob 文件上传 js中的文件处理和文件上传掌握得更扎实&#xff0c;有更深入的理解&#xff0c;底层原理 ps.项目中使用插件上传 filereadermime类型筛选单文件的2种处理方案多文件&文件上传进度管控 Ajax文件上传时&#xff1a;Formdata、File、Blob的关系-腾讯云开发者…

基于Java端游账号销售管理系统设计实现(源码+lw+部署文档+讲解等)

博主介绍&#xff1a; ✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战 ✌ &#x1f345; 文末获取源码联系 &#x1f345; &#x1f447;&#x1f3fb; 精…

C语言 --- 文件操作(万字详解)

文章目录 前言&#x1f31f;一、为什么使用文件&#x1f31f;二、什么是文件&#x1f30f;2.1程序文件&#xff1a;&#x1f30f;2.2数据文件&#xff1a;&#x1f30f;2.3文件名&#xff1a; &#x1f31f;三、文件的打开和关闭&#x1f30f;3.1文件指针&#xff1a;&#x1f…

TDEngine 调优 - 高速查询及插入

TDEngine 调优 - 高速查询及插入 一、基本参数二、TDEngine大数据核心2.1 vnode分片2.1.1 表分布不均匀2.1.2 vnode分布不均匀2.2 时间段分区 三、数据库性能优化3.1 数据文件3.1.1 maxrows 和 minrows3.1.2 数据的保留策略duration\days 3.2 磁盘IO - vgroups3.3 性能优化实战…

「网络编程」第二讲:网络编程socket套接字(一)

「前言」文章是关于网络编程的socket套接字方面的&#xff0c;下面开始讲解&#xff01; 「归属专栏」网络编程 「笔者」枫叶先生(fy) 「座右铭」前行路上修真我 「枫叶先生有点文青病」 「每篇一句」 春风得意马蹄疾&#xff0c;一日看尽长安花。 ——孟郊《登科后》 目录 一…

这有可能是全网最好的《基于CUDA的GPU并行程序优化实战课程》!预售开启!

大模型一出&#xff0c;各类企业的各类“模型”竞赛般的亮家伙&#xff0c;算力时代抢先到来。2023年4月超算互联网的正式部署&#xff0c;标志着&#xff0c;很快&#xff0c;越来越多的应用都需要巨大的计算资源。 这给传统的计算机体系结构带来了巨大的挑战&#xff0c;计算…

C语言指向结构体的指针(二)

示例 #include <stdio.h> void main(){struct student{char name[10];int age;char *xiaoming;}stu1{"豪哥",23,"zz"},*p;p &stu1;//struct student stu2 {"豪哥",23};printf("结构体指针变量p的姓名是:%s,年龄是:%d,小名是&am…