首页 >> 大全

4.基于 qiankun 的微前端实战

2023-09-15 大全 22 作者:考证青年

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

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

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

官网

微前端实现__微前端实现方式以及代码

目录

1.什么是微前端

2.微前端的好处

3.现有的微前端方案

3.1

3.2 -spa

3.3

4.基于 的微前端实战

4.1 基座改造

4.1.1 安装

4.1.2 修改入口文件

4.2 React 微应用改造

4.2.1 修改微应用入口文件

4.2.2 新增 -path.js

4.2.3 修改 配置

4.3 Vue 微应用改造

4.3.1 使用 Vite 创建微应用

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

4.3.3 修改微应用入口文件

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

4.4.1 安装 umijs/ 插件

4.4.2 配置 .umirc.ts

4.4.3 修改微应用入口文件

5. 常见需求的实现

5.1 样式隔离

5.2 微应用之间的跳转

hash(推荐)

5.3 公共依赖加载

5.4 全局状态管理

1.什么是微前端

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

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

_微前端实现_微前端实现方式以及代码

2.微前端的好处

3.现有的微前端方案 3.1

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

但是 也有局限性:

3.2 -spa

-spa 官网

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

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

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

但是 -spa 也有局限性:

3.3

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

有什么优势呢?

4.基于 的微前端实战

项目结构:

├── micro-base // 基座
├── sub-react // react 子应用,create-react-app 创建的应用,使用 webpack 打包
├── sub-vue // vue 子应用,vite 创建的应用,使用 vite 打包
└── sub-umi // umi 脚手架创建的子应用

4.1 基座改造

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

4.1.1 安装

// 安装 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,解析里面的 jsactiveRule: "/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 发生变化,便会自动触发 的匹配逻辑:所有 规则匹配上的微应用就会被插入到指定的 中,同时依次调用微应用暴露出的生命周期钩子

方法介绍:

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

4.2 React 微应用改造

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

4.2.1 修改微应用入口文件

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

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

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

let root: Root// 将 render 方法用函数包裹,供后续主应用与独立运行调用
function render(props: any) {const { container } = propsconst dom = container ? container.querySelector('#root') : document.getElementById('root')root = createRoot(dom)root.render()
}// 判断是否在 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 新增 -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 修改 配置

// 在根目录下新增 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 vite@

_微前端实现_微前端实现方式以及代码

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

npm i vite-- # yarn add vite--

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})]
})

注意事项:

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/ 插件

npm i @umijs/

4.4.2 配置 .umirc.ts

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

4.4.3 修改微应用入口文件

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

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

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 样式隔离

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

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

解决方法:

5.2 微应用之间的跳转

举个例子:

如何解决这个问题呢?

hash(推荐)

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

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

有两种办法可以跳转:

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

// 重写函数
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 = argumentswindow.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 等),可以用 的方式来引入,减少加载重复包导致的资源浪费

方式:

以 axios 为例:


// 修改config-overrides.js
const { override, addWebpackExternals } = require('customize-cra')module.exports = override(addWebpackExternals ({axios: "axios",}),
)

5.4 全局状态管理

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

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

基座

// 基座初始化
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)
}

关于我们

最火推荐

小编推荐

联系我们


版权声明:本站内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 88@qq.com 举报,一经查实,本站将立刻删除。备案号:桂ICP备2021009421号
Powered By Z-BlogPHP.
复制成功
微信号:
我知道了