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

core-js常见于qiankun中的多份polyfill冲突问题

问题

开门见山,你可能会在 qiankun 等微前端体系中,有多个子应用时,发生这样的加载崩溃问题:

Cannot redefine property: DEG_PER_RAD

Cannot redefine property: RAD_PER_DEG

实际上 DEG_PER_RADRAD_PER_DEG 都是 Math 上的静态常量,在以下的描述中,我们就以 Math.DEG_PER_RAD 为例进行拆解。

原因拆解

崩溃的根本原因是,core-js 在 3.23.0 做出了一个改动:不能对 Math.DEG_PER_RAD 重复赋值( 相关 issue 详见 #1091 )。

在 core-js 3.23.0Math.DEG_PER_RAD 设定为了 nonConfigurable: truenonWritable: true 的( 代码详见 esnext.math.deg-per-rad.js ),所以当加载了 >= 3.23.0 的 polyfill 后,不能对 Math.DEG_PER_RAD 重新写入了,此时再加载 < 3.23.0 的 polyfill ,就会发生崩溃报错。

而先加载了 < 3.23.0 的 polyfill ,再加载 >= 3.23.0 的话,是没问题的。

为什么常会发生在微前端下?

通过问题拆解,我们发现此报错是与 core-js 不同版本的加载 顺序 强相关的,而在 qiankun 类似的微前端体系下,往往每个子应用都会有一份 polyfill ,所以他们可能会发生本文中的致命冲突,导致应用彻底崩溃。

你可以在全局变量 window['__core-js_shared__'] 中看到当前项目中有多少 core-js 版本:

解法

这里我们先不进一步探究,直接提供解法:

要解的无非是 Math.DEG_PER_RADMath.RAD_PER_DEG 的问题,那我们直接排除这两个 polyfill 就可以了,他们在 core-js 中的名字是 esnext.math.deg-per-radesnext.math.rad-per-deg

如何排除?

对于社区中大部分的脚手架来说,他们的 babel polyfill 策略都是 usage ,所以当你不使用这两个 Math.xxx 常量的时候他是不会引入 polyfill 的。

既然发生了此问题,说明你的 polyfill 大概率是 entry 策略(此处不再展开讲解 babel polyfill 策略),是全量引入的,所以你应该找到相关源头,排除掉他们。

由于排除的手段和 框架 / 脚手架 实现逻辑强相关,所以本文不做具体描述,在排除过程中,除了可以定点排除 esnext.math.deg-per-radesnext.math.rad-per-deg 外,考虑到未来如果新增其他的 Math.constant 常量,也要再排除,同时 esnext.math.xxx 都是 stage 1 的 polyfill (详见 proposal-math-extensions ),几乎不会有人使用到,全部排除了也是没什么风险的,故可以把 esnext.math.xxx 全部过滤掉。

当你无法触及、或不了解框架行为,不能自行解决时,可以考虑到相关框架、脚手架的 issue 区反馈,寻求维护者的帮助。

swc 的 polyfill 策略排除法

为了讲解的更全面,此处我们还提供 swc 的 polyfill 排除解法。对于 swc 来说,我们推荐使用的 polyfill 策略是人工指定 includes 方法(因为 swc 的 usage 策略速度慢,且更新不及时),详见:

  • 《 swc兼容polyfill的权衡与选择 》

那在获取 polyfill 列表结束后,人工过滤掉 esnext.math.xxx 的 polyfill 即可:

// 过滤部分逻辑
const filteredList = (list as string[]).filter(line => {
  // https://github.com/zloirock/core-js/issues/1091
  // Prevent `Math.DEG_PER_RAD` / `Math.RAD_PER_DEG` constant override problem in qiankun micro app
  return !line.startsWith('esnext.math.')
})

其他可能的解法

除了从 core-js 本身上来解决该问题,这里再提供一些其他的解法思路:

  1. 将主应用、子应用全部升级到最新的 core-js 版本,避开含有 < 3.23.0core-js 情况,可解此问题。

  2. 因为主应用含有 polyfill ,子应用没有独立使用的场景时,无需 polyfill ,把子应用的 polyfill 关掉就可以了。

总结

core-js 本身是没问题的,只不过你加载了多份 polyfill ,那就说不准了,这就是:微前端路漫漫其修远兮,只有踩过了坑才知道事出不易。

由于本文探讨的问题场景比较特定和深入,更多的面向对 webpack 比较了解的用户,跳过了很多基础概念的介绍,希望对你有所帮助。

相关文章:

  • 开发公司 网站建设/人工智能培训课程
  • zbolg搭建的网站/西安网络seo公司
  • 动漫电影做英语教学视频网站有哪些/百度指数网站
  • 搭建网站需要什么软件/想在百度上推广怎么做
  • wordpress缩略图只生成full/产品seo怎么优化
  • 成都手机网站建设哪/网站建设seo优化培训
  • JavaWeb基础(二) HTTP、Tomcat、Servlet介绍
  • 《Linux Shell脚本攻略》学习笔记-第五章
  • VMware17虚拟机安装Ubuntu最新版本(Ubuntu22.04LTS)详细步骤
  • [极客大挑战 2019]Upload
  • 指针习题(1):升序排序
  • 【自学Docker】Docker环境命令
  • Nginx高并发实现原理学习
  • 32位机虚拟内存地址最大0xFFFFFFFF是怎么得出来的?内存大小与地址的对应关系以及计算方法?
  • 谷歌账号被封怎么办?谷歌账号解封申诉步骤请收好!
  • 分布式-数据库治理
  • LeetCode题解 回溯(五):332 重新安排行程;51 N皇后;37 解数独 —— hard三连
  • 注意力FM模型AFM