Vite+Antd+Micro-app中iframe模式下样式闪烁的问题

在Vite中使用Micro-app进行微前端开发,做的过程中发现在iframe模式下,无论是首屏加载还是中间的路由切换都会出现antd样式闪烁;具体如下:

  1. 按钮的样式从最初始状态变为Antd的Button样式,有颜色改变时,最为明显
  2. 输入框由input初始样式变为Antd的样式
  3. 所有的Antd组件都是从浏览器的默认样式加载为Antd的样式

解决历程

  1. 既然是样式后加载,那么是否可以进行样式预设,当Antd样式加载时,就不会出现明显的闪烁
js 复制代码
// index.html
<!-- iframe 模式:预设关键样式,避免 FOUC -->
    <style>
      /* 预设主题色,避免按钮颜色闪烁 */
      .ant-btn-primary {
        background-color: #7470e9;
        border-color: #7470e9;
        color: #fff;
      }

      .ant-input {
        height: 40px;
        font-size: 16px;
        padding: 6.5px 11px;
        border-width: 1px;
        border-style: solid;
        border-color: #d9d9d9;
        border-radius: 6px;
      }

      .ant-btn {
        border-width: 1px;
      }
    </style>

解决效果:肉眼可见的闪烁没有了,但是缺点也很明显,就是需要把用到的所有的Antd组件的基础样式或者叫引起明显抖动的样式预设,避免明显抖动

  1. 仿照Antd给Next.js做的@ant-design/nextjs-registry库,来解决提前加载样式的问题

@ant-design/nextjs-registry是如何解决在Next.js中首屏加载时闪烁的问题,是在Next.js渲染组件时,使用@ant-design/cssinjs提供的const styles = extractStyle(cache, true)能力

js 复制代码
'use client'
const AntdRegistry = ({ children }) => {
  useServerInsertedHTML(() => {
    // 在服务端渲染时执行
    const styleText = extractStyle(cache, true);
    return <style dangerouslySetInnerHTML={{ __html: styleText }} />;
  });

  return <StyleProvider cache={cache}>{children}</StyleProvider>;
};

将含Antd的HTML代码全部发给浏览器,这样渲染的时候就不会出现样式闪烁,但是 这个是Next.js的专属能力 ,CSR(客户端渲染)的做不到,因为Antd的组件样式是在加载组件时才会放到cache中,也就是说在App.tsx中使用下面的代码包括,是没有用的

js 复制代码
useEffect(() => {
    // 在客户端挂载时执行
    const styleText = extractStyle(cache, true);
    const styleElement = document.createElement('style');
    styleElement.textContent = styleText;
    document.head.insertBefore(styleElement, document.head.firstChild);
  }, []);

这个代码在执行时styleText啥也没有,加载组件在useEffect之后,此时我们已经很接近真相了

  1. 我发现一个现象,在SPA页面中,样式只会在首屏时闪烁,进入其他页面后,并没有闪烁,已加载的样式被缓存了,查询之后,发现是Antd的cache在做缓存判断,然后我查看了子应用的样式发现Micro-app给每个样式否加了前缀micro-app[name=hospital-gateway]
css 复制代码
micro-app[name=hospital-gateway] ._hospital-search-wrapper_v077x_1 ._search-operate_v077x_5 button {
    width: 100px;
    margin-left: 8px;
}

这个前缀导致了Antd的cache失效,而且每次路由切换时,Micro-app都会将Antd原来的样式重写为有micro-app[name=hospital-gateway]前缀的样式,这就是导致每次样式抖动的根本原因。

  1. 找到根源后,就看如何去掉这个前缀,iframe模式下,样式是天然隔离的,是不需要类似with模式下的样式前缀的,而且去掉前缀,也可以启用Antd的样式缓存,避免切换路由时的样式抖动,最后发现在添加disable-scopecss属性就可以去掉自动添加的前缀
js 复制代码
<micro-app name={name} url={url} baseroute keep-alive disable-scopecss />
相关推荐
FungLeo11 小时前
成为全栈·React 管理后台篇·总复盘:从“接口能调通”到“后台值得使用”
前端·react.js·前端框架·项目复盘·成为全栈
Csvn12 小时前
并发模式:让渲染学会排队、插队和让路
前端
可乐鸡翅yeah_12 小时前
新手梳理:M3U8 线上问题,哪些是前端锅,哪些是后端锅
前端·ios·音视频·实时音视频·m3u8·音视频在线播放
Flynt12 小时前
Linear 用 1000 个 PR 换掉 styled-components,我写了 200 个按钮,把这笔账复现了一遍
前端·css·preact
JavaGuide13 小时前
NVIDIA 又开源了!这次给 AI Agent 加上权限管控
前端·后端
excel13 小时前
prisma 如何处理数据库竞态
前端·数据库·后端
莪_幻尘15 小时前
Skill 体检:30 个 Skill 全凭感觉?体检器先自曝了 8 个“假 0 分
前端·人工智能·llm
风骏时光牛马15 小时前
AI模型综合能力评测:性能、指令遵循与多场景实测对比
前端
Frag0ut15 小时前
Chrome与Chromium内核浏览器在Windows 11上的新特性全景解析
前端·chrome·windows·web安全·chromium·gemini ai·playready drm
hiahiahia12315 小时前
实现完整 Tool Dispatcher
开发语言·前端