gpt4 book ai didi

javascript - 外部脚本中的全局 polyfill 破坏网站功能的风险是什么?

转载 作者:行者123 更新时间:2023-11-29 23:03:07 24 4
gpt4 key购买 nike

@babel/polyfill 的文档有以下注释:

If you are looking for something that won't modify globals to be used in a tool/library, checkout the transform-runtime plugin.

关于 transform-runtime文档,它说如下:

While this [@babel/polyfill usage] might be ok for an app or a command line tool, it becomes a problem if your code is a library which you intend to publish for others to use or if you can't exactly control the environment in which your code will run.

更一般地说,很多解释 polyfill 使用的文章都说,如果您关心污染全局命名空间,您可能想要使用不同的解决方案。

据我了解,大多数 polyfill 都是有条件地加载的。如果一个实现已经存在,polyfill 将不会覆盖它。我的问题是:在什么样的情况下,外部脚本中的 polyfill 会导致现有网站崩溃?到目前为止我能找到的唯一原因是外部脚本可能比网站本身的代码更早加载 polyfill。这可能会导致问题,但是当这些 polyfill 基于 web 标准时,它们的行为应该是相同的。仍然存在严重冲突的可能性有多大?

我在 github issue 上发现了一个有趣的讨论。 .不过,这主要讨论 NPM 生态系统中的模块,而我主要对促进小部件或嵌入等事物的外部脚本感兴趣。

感谢任何个人经验或指向有关该主题的讨论和文章的链接!

更新:这个问题的主要原因之一是转换运行时存在一些问题。随着 core-js 和 babel 的新发布,​​这些问题似乎已经得到解决。不管怎样,我仍然对上述原始问题的答案感兴趣。

最佳答案

嗯,polyfill 很少是完美的,正如您所说,它们几乎都是有条件地工作的。

假设 library-1 为名为 Interface 的功能注入(inject)了它自己的 polyfill (polyfill-A)。
这个 polyfill-A 可以很好地实现 Interface 的完整 API 的几个方法,例如,官方 API 可能是这样的

interface Interface {
constructor(optional (Interface or DOMString) foo);
undefined doSomething();
undefined doSomethingElse();
};

但在构造函数中传递一个 Interface 实例可能只是稍后在规范中添加,或者 doSomethingElse 可能已被该 polyfill 省略,或者根本没有经过测试正确并且所有这些小遗漏对于 library-1 可能没问题,因为它们不使用任何这些。
现在,当 library-2 自己的 polyfill 将检查是否已经有可用的 Instance 构造函数时,它会发现是的,它已经被定义,因此不会重新 -实现它。
但是,library-2 可能需要在构造函数中传递一个接口(interface),或者可能需要调用它的 doSomethingElse() 方法。当它尝试这样做时,代码会崩溃,因为即使 library-2 的作者确实包含了一个正确实现这两个功能的 polyfill,library-1 的 polyfill 实现是运行和可访问的。

<script>
// library-1.js
(function polyfillInterface() {
if (typeof Interface !== "function") {
class Interface {
constructor(foo) {
this.foo = foo.toUpperCase();
}
doSomething() {
return this.foo + "-bar";
}
}
globalThis.Interface = Interface;
}
})();
{
// for library-1, everything works well
const instance = new Interface("bla");
console.log(instance.doSomething());
}
</script>

<script>
// library-2.js
(function polyfillInterface() {
if (typeof Interface !== "function") {
class Interface {
constructor(foo) {
if (foo instanceof Interface) {
this.foo = foo.foo;
}
else if (typeof foo === "string") {
this.foo = foo.toUpperCase();
}
else {
throw new TypeError("neither an Interface nor a DOMSrting");
}
}
doSomething() {
return this.foo + "-bar";
}
doSomethingElse() {
return this.foo.toLowerCase() + "-bar";
}
}
globalThis.Interface = Interface;
}
})();
{
// for library-2, everything is broken
const instance_1 = new Interface("bla");
try {
console.log(instance_1.doSomethingElse());
}
catch(err) {
// instance_1.doSomethingElse is not a function
console.error(err);
}
// TypeError: foo.toUpperCase is not a function
const instance_2 = new Interface(instance_1);
}
</script>

而且这可能是很难确定的事情,例如 Promise.then() 应该在与它们解决(在微任务队列中)相同的事件循环中触发,而不是在下一个事件循环中触发就像普通任务一样,许多 Promise 库可能一直在使用 setTimeout(fn, 0) 来实现异步性,而不是例如在可用时使用 MutationObserver。 p>

这就是为什么在编写库时,最好链接到 polyfill,但不要自己包含它们。

关于javascript - 外部脚本中的全局 polyfill 破坏网站功能的风险是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55241379/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com