当前位置: 首页 > news >正文

微前端在项目中常见的问题

本篇博客主要介绍在使用微前端架构时最常见的污染问题及处理方法。

微前端架构

在微前端架构中,如何解决多个子应用见的样式污染与全局变量冲突

  • 样式污染:

    原因是因为在子应用中使用了相同的类名,或者直接修改了全局标签的样式

    1. 采用qiankun自带的sandbox配置开启隔离。
    • 严格沙箱:利用shadow Dom将子应用整个包裹,这是最彻底的隔离,因为shadow Dom内部的样式不会溢出道外部。
    • 实验性沙箱:quankun会动态地为子应用的所有css选择器前缀增加一个特殊的属性选择器,
    1. CSS Modules/CSS-in-JS

    从开发规范上解决问题,在打包子应用时,利用webpackcss-loader开启modules模式,将类名混淆为唯一的哈希值

    1. BEM命名规范+样式前缀

      在css预处理器(Sass/Less)中,为每个子应用配置一个唯一的命名空间前缀

  • 变量隔离

当多个应用都想在window对象挂载localStorage、 vue 实例和全局配置时,冲突就会发生

  1. 采用qiankun的JS沙箱机制:

    qiankun会默认开启JS沙箱,它主要是分为3种

    • SnaoshotSandbox(快照沙箱):适用于不支持Proxy的旧浏览器,子应用挂载前记录window状态,卸载时对比并恢复
    • LegencySandbox(单实例沙箱):记录快照,但是在操作上更高效
    • ProxySandbox(多实例沙箱):最核心、强大的机制。它为每个子应用都创建了一个“伪window”,通过proxy拦截子应用对window的所有操作
      • 读取时:先看伪window有没有,没有再去全局真window找
      • 写入时,只写入在伪window中
  2. 避免显示的window挂载

    在微前端环境下,尽量使用props传递数据,而不是只写写死在window.xx上。

    • 统一封装基于initGlobalStated的通信机制或者自定义customEvent进行跨应用状态同步

封装GlobalState代码实现:

思路:

  • 在基座中:初始化并封装一套“状态分发器”
  • 子应用端:封装一个高阶组件或者hook,自动监听与销毁
  1. 基座端的封装:在基座中定义状态池和修改方法
// main-app/src/utils/actions.js
import { initGlobalState } from 'qiankun';const initialState = {user: { name: 'Alice', role: 'Admin' }, // 初始状态 [cite: 1]theme: 'light',auth: []
};const actions = initGlobalState(initialState);actions.onGlobalStateChange((state, prev) => {// 可以在这里统一处理日志打印或权限校验console.log('[Main App State Change]:', state, prev);
});// 增加自定义的 get 方法(原生不支持,需自行记录最后一次 state)
let currentState = initialState;
actions.onGlobalStateChange((state) => {currentState = state;
});export const getGlobalState = () => currentState;
export default actions;
  1. 在子应用端封装Hook
// micro-app/src/hooks/useGlobalState.js
import { useState, useEffect } from 'react';export function useGlobalState(props) {const [globalState, setGlobalState] = useState({});useEffect(() => {// 监听全局状态变化 props.onGlobalStateChange((state, prev) => {setGlobalState(state);}, true); // true 表示立即触发一次return () => {// 这里的销毁逻辑由 qiankun 在子应用卸载时统一处理,// 但在组件级别,我们需要确保引用不产生副作用。};}, [props]);const updateState = (newData) => {props.setGlobalState({ ...globalState, ...newData });};return { globalState, updateState };
}

如果用户在多个子应用中频繁的修改同一个状态,导致页面出现卡顿,如何处理?

这里我们需要思考:是否需要按需订阅,也就是说在封装时增加selector函数,只有子应用关心特定字段变化时,才会出发setState,避免变量全局污染;其次需要考虑状态合并问题,防止高频修改阻塞主线程。

优化后的代码:

基座端:增加防抖函数,多次改变合并为一次,减少通信频次

import { initGlobalState } from 'qiankun';
import { debounce } from 'lodash';const initialState = {dataList: [], // 假设这是高频更新的大数据config: {}
};const actions = initGlobalState(initialState);// 原始更新方法
const rawSetState = actions.setGlobalState;// 封装防抖更新:在 16ms(约一帧)内多次调用只会触发一次
actions.setGlobalState = debounce((state) => {console.log('--- 批量更新执行 ---');rawSetState(state);
}, 16);export default actions;

子应用端按需更新Hook

import { useState, useEffect, useRef } from 'react';
import { isEqual } from 'lodash'; // 用于深比较export function useSelectGlobalState(props, selector) {// selector 定义:(state) => state.someFieldconst [selectedState, setSelectedState] = useState(() => selector(window?.currentGlobalState || {}));const lastStateRef = useRef(selectedState);useEffect(() => {const unread = props.onGlobalStateChange((state) => {const nextState = selector(state);// 核心优化:只有当 selector 选中的数据发生变化时,才触发 React 更新if (!isEqual(lastStateRef.current, nextState)) {lastStateRef.current = nextState;setSelectedState(nextState);}}, true);return () => unread();}, [props, selector]);return selectedState;
}
http://www.jsqmd.com/news/427723/

相关文章:

  • 2026最新江西老人护理公司TOP5评测!专业家政服务标杆榜单发布,构建暖心养老服务体系 - 十大品牌榜
  • 2026年质量好的1500v高压直流接触器/电池包高压直流接触器高口碑品牌推荐 - 品牌宣传支持者
  • JDK 21 新特性
  • 2026年评价高的高位工业设备钐钴永磁/钐钴永磁镀层高口碑品牌推荐 - 品牌宣传支持者
  • 2026年口碑好的净水设备钣金加工/润滑脂泵钣金加工供应商怎么选 - 品牌宣传支持者
  • 2026 年激光防护镜优质厂家推荐(防护镜、防护眼镜、激光防护眼镜)高口碑品牌榜单 - 品牌企业推荐师(官方)
  • 2026最新!AI论文工具 千笔写作工具 VS 灵感风暴AI,本科生首选!
  • 2026年评价高的缓冲集成阻尼铰链/静音集成阻尼铰链采购指南厂家怎么选 - 品牌宣传支持者
  • 2026最新江西育儿嫂公司TOP5评测!专业家政服务权威榜单发布,构筑品质家庭服务新生态 - 十大品牌榜
  • 2026年评价高的旋压加工/汽车配件旋压加工专业制造厂家推荐 - 品牌宣传支持者
  • 2026最新江西住家保姆公司TOP5评测!专业家政服务权威榜单发布,打造品质居家新体验 - 十大品牌榜
  • 毕业论文神器!降AIGC平台 千笔AI VS 知文AI,MBA专属更高效
  • 2026最新江西家政服务/月嫂/育儿嫂/老人护理/住家保姆/不住家保姆公司TOP5评测!专业标杆服务典范权威榜单发布 - 十大品牌榜
  • python+flask的高校二手交易网站设计与实现_9e19y639
  • 学霸同款!风靡全网的降AIGC网站 —— 千笔AI
  • 2026年口碑好的智能温控烘箱/工业烘箱供应商怎么选 - 品牌宣传支持者
  • python_vue基于flask的教师科研课题征集与发布系统设计与实现_q6g566bf
  • 2026最新江西月嫂公司TOP5评测!标准引领+专业服务权威榜单发布,筑牢家政服务品质标杆 - 十大品牌榜
  • redis可视化客户端工具推荐和功能比较
  • 成都火锅新宠儿:2026口碑推荐品牌榜单来袭,火锅/成都火锅/社区火锅/牛肉火锅/老火锅/美食,火锅品牌口碑排行 - 品牌推荐师
  • 【2026】 LLM 大模型系统学习指南 (76)
  • 2026最新江西家政服务公司TOP5评测!标准化服务/品牌标杆权威榜单发布,构筑品质居家新生态 - 十大品牌榜
  • 技术日报|WiFi穿墙追踪项目两日暴涨破万星,阿里AI沙箱OpenSandbox今日强势夺银
  • 2026最新江西不住家保姆公司TOP5评测!专业家政服务权威榜单发布,打造品质居家生活新标杆 - 十大品牌榜
  • 2026年热门的泡沫箱/云南泡沫箱实力品牌厂家推荐 - 品牌宣传支持者
  • python+flask的舞蹈文化中心平台设计与实现_95quaxsf
  • 无题1
  • 软考高项:第16章:项目采购沟通管理(占分分析/考点/题)
  • RVC快速部署体验:开箱即用的AI语音转换工具
  • python+flask的英语学习平台_ja5h443a