Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
boogie-ben opened this issue Jan 25, 2024 · 5 comments
Open

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

boogie-ben opened this issue Jan 25, 2024 · 5 comments
Assignees
Labels
accepted feature request is accepted

Comments

@boogie-ben
Copy link

boogie-ben commented Jan 25, 2024

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行

Copy link

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

Copy link

github-actions bot commented Jan 25, 2024

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

@uyarn
Copy link
Collaborator

uyarn commented Jan 25, 2024

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

@uyarn uyarn transferred this issue from Tencent/tdesign-vue-next Jan 25, 2024
Copy link

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

@boogie-ben
Copy link
Author

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

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

@uyarn uyarn added the accepted feature request is accepted label Jan 28, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
accepted feature request is accepted
Projects
None yet
Development

No branches or pull requests

3 participants