Tencent / tdesign-icons

A mono repo for TDesign Icons
https://tdesign.tencent.com/design/icon
MIT License
46 stars 27 forks source link

[Icon] svg精灵图的实现过程适配微前端环境 #91

Open boogie-ben opened 8 months ago

boogie-ben commented 8 months ago

tdesign-vue-next 版本

1.8.0

问题

在micro-app、wujie微前端环境下(qiankun未测试)

使用t-iconiconfonticon组件进行图标渲染,都会发起网络请求,这个网络请求的问题在微前端环境下因其实现流程会出现问题

经过排查发现是上述的图标组件渲染行为在micro-app环境下的的问题,生成svg精灵图 script 标签被插入了多次,导致生成了多个巨大的svg精灵图。

原因

微前端环境下,子应用生成的script会被拦截,不会放到子应用的body中,而是放到沙箱中执行,所以图标组件判断这个生成svg精灵图的 script 标签是否存在时,会一直判断为找不到。第10行

另外,微前端框架中,对子应用的 insertAdjacentHTML 方法没有进行代理或拦截等处理,所以这个子应用里的script执行该方法插入svg精灵图时会把HTML内容插入到基座应用的body中 ,插入位置不符合预期 image

所以,子应用页面上使用了多个图标组件,导致每一个图标组件都会生成一个 script 和 全量图标的svg精灵图。(我运行的项目首页使用了多个图标,正常情况下渲染5000+个dom节点,在微前端环境下生成了90000+个节点)

建议

目前的解决:在子应用的index.html中body内写死这个 script ,那么在图标组件挂载时找这个 script 时就会判断已经存在

<script class="t-svg-js-stylesheet--unique-class" ignore="true" src="https://tdesign.gtimg.com/icon/0.2.0/fonts/index.js"></script>

但弊端是发现这个src的目标地址是附带图标组件的版本号的,如果日后组件库版本更新时更改了类名或者src的url,导致Icon组件内这个查询这个script是否存在时判断为无,导致又出现了上述问题,所以还需建议组件修改实现流程。

  1. script内插入svg精灵图时代码确保插入到了子应用中 原script代码

    var svgCode = '<svg></svg>' // svg精灵图代码
    /*
    if (document.body) {
       document.body.insertAdjacentHTML('afterbegin', svgCode);
    } else {
       document.addEventListener('DOMContentLoaded', function () {
           document.body.insertAdjacentHTML('afterbegin', svgCode);
       });
    }
    */
    var svg = document.createRange().createContextualFragment(svgCode).children[0]; // 预先生成svg节点,为了使用插入节点的方法
    if (document.body) {
       document.body.appendChild(svg);
    } else {
       document.addEventListener('DOMContentLoaded', function () {
           document.body.appendChild(svg);
       });
    }
    • 为了使用已经被微前端框架进行代理后的常见的插入节点方法,如insertBeforeappendChild,先把svg精灵图的html代码生成为一个svg节点后在插入到子应用的body中
    • 原本的 insertAdjacentHTML 会把精灵图作为body的第一个子节点插入,此处使用 appendChild 的原因是微前端框架对子应用的firstchild未进行拦截处理(代价大),所以这行代码 document.body.insertBefore(svg, document.body.firstchild) 实际上也是插入到子应用body的末端,因为 document.body.firstchild 返回的是基座应用的第一个字节的。
    • svg精灵图插入的位置在body顶部和尾部貌似都能正常使用?
  2. 因为上述步骤确保svg精灵图正确插入到子应用的body中了,Icon 组件判断生成svg精灵图是否存在时,可把对 script 的查找更改为对svg查找(给svg精灵图加上一个类名或id),就能避免子应用的 script 被沙箱转移位置导致body中找不到的问题 第10行

github-actions[bot] commented 8 months ago

👋 @boogie-ben,感谢给 TDesign 提出了 issue。 请根据 issue 模版确保背景信息的完善,我们将调查并尽快回复你。

github-actions[bot] commented 8 months ago

♥️ 有劳 @uyarn 尽快确认问题。 确认有效后将下一步计划和可能需要的时间回复给 @boogie-ben 。

uyarn commented 8 months ago

最近我的业务也遇到配合wujie使用的这个问题了 transfer到图标库处理 如果有兴趣也可以提交个PR

github-actions[bot] commented 8 months ago

👋 @boogie-ben,感谢给 TDesign 提出了 issue。 请根据 issue 模版确保背景信息的完善,我们将调查并尽快回复你。

boogie-ben commented 8 months ago

最近我的业务也遇到配合wujie使用的这个问题了 transfer到图标库处理 如果有兴趣也可以提交个PR

PR我就不提了,我怕改Angular的部分弄错了,没写过