JavaScript ES6规范支持module imports或ES6 modules。
静态导入非常易于使用,并且已经具有quite a good browser support,但是动态导入为still lacking behind。因此,您的代码有可能使用静态模块(当不支持这些模块时,代码甚至不会执行),但浏览器可能会错过对dynamic导入的支持。因此,检测动态加载是否有效(在尝试实际加载代码之前)可能很有用。还有as browser detection is frowned upon,我当然想使用特征检测。
用例可能会显示错误,回退到其他一些数据/默认/加载算法,为开发人员提供了在模块中动态加载(例如,以延迟模式样式的数据)优势,同时允许回退到直接传递数据等。基本上,可以使用特征检测的所有常用情况。
现在,由于动态模块是通过import('/modules/my-module.js')
导入的,因此显然会试图仅检测该函数是否存在,例如:
// this code does NOT work
if (import) {
console.log("dynamic import supported")
}
我猜想,对于每个其他函数?都可以,但是问题似乎是:import
分别是a reserved keyword in ECMAScript,现在显然也用于指示静态导入,这不是真正的功能。正如MDN所说,它就像“功能类”。
import()
导致语法错误,因此这实际上不是可用的,并且import("")
导致拒绝的Promise,这可能是有用的,但看起来确实有点黑/像变通办法。此外,它仅需要异步上下文(await
等)用于特征检测,这并不是很好。typeeof import
也直接失败,由于关键字(“意外令牌:关键字'import'”)而导致语法错误。
那么,可靠地检测浏览器是否支持dynamic ES6模块的最佳方法是什么?
编辑:正如我看到的一些答案一样,请注意,该解决方案当然应该尽可能地普遍可用,例如CSPs可能会阻止the use of eval
,在PWA中,您不应假定自己一直在线,因此仅尝试请求某个任意文件可能会导致错误的结果。
在更多研究中,我发现了eval
,并带有用于动态特征检测的JS必不可少的部分:
为此,所有功劳都来自GitHub function supportsDynamicImport() {
try {
new Function('import("")');
return true;
} catch (err) {
return false;
}
}
document.body.textContent = `supports dynamic loading: ${supportsDynamicImport()}`;
!
无论如何,这有两个问题:
唯一想到的是true
或类似eval
的解决方案,例如使用eval
插入script
标签。您有import()
使用import()
或类似的名称。除非它在您的模块映射中,否则它是无效的模块说明符,因此不应引起网络请求。
foo
更方便,但会与某些CSP冲突:
eval
避免let supported = false;
try {
eval("try { import('foo').catch(() => {}); } catch (e) { }");
supported = true;
} catch (e) {
}
document.body.insertAdjacentHTML("beforeend", `Supported: ${supported}`);
:
eval
[它们都在Chrome,Chromium Edge,Firefox等上默默报告let supported = false;
const script = document.createElement("script");
script.textContent = "try { import('foo').catch(() => { }); } catch (e) { } supported = true;";
document.body.appendChild(script);
document.body.insertAdjacentHTML("beforeend", `Supported: ${supported}`);
;和true
在Legacy Edge上(存在语法错误)。
请注意,false
“调用”周围的try
/ catch
只是为了捕获有关模块说明符的所有同步错误,以避免使错误控制台混乱。
实际上,现在我考虑了,您不必动态生成该脚本:
import()