为自定义元素加载polyfill的最佳方式是什么?
问题描述:
我目前正在玩弄自定义元素。我正在努力寻找正确的方式(或者感觉像正确的方式)来填充缺乏支持的浏览器(看起来只有Firefox?)。为自定义元素加载polyfill的最佳方式是什么?
我目前做如下:
if ('customElements' in window) {
var e = document.createElement('script');
e.src = '/static/elements/my-element.js';
document.body.appendChild(e);
} else {
var e = document.createElement('script');
// customElements
e.src = 'https://cdnjs.cloudflare.com/ajax/libs/webcomponentsjs/1.0.8/webcomponents-sd-ce.js';
e.onload = function() {
var c = document.createElement('script');
// ShadyCSS
c.src = '/static/js/custom-style-interface.min.js';
c.onload = function() {
var i = document.createElement('script');
i.src = '/static/elements/my-element.js';
document.body.appendChild(i);
}
document.body.appendChild(c);
}
document.body.appendChild(e);
}
这工作,但显然是极其低效(特别是在慢/高延迟网络),也看起来很嘈杂。在尝试支持Firefox之前,我可以简单地这样做:
<script src="/static/elements/my-element.js"></script>
现在我有上面这个憎恶。必须有更好的方法,但我似乎无法找到一个。
我怎样才能确保customElement和ShadyCSS polyfills在my-element.js
之前运行,而不会延迟下载那么多?任何指针都非常感谢!
编辑: 现在我用另一种方法,我将在这里添加。我不认为这是完美的,但似乎比我的第一种方法更好,或者迫使每个人下载polyfills,无论他们是否需要它们。
function insertScript(url, downloadAsync) {
const script = document.createElement('script');
document.head.appendChild(script);
script.async = downloadAsync;
script.src = url;
return script;
}
function downloadAsync(url) {
return new Promise((resolve, reject) => {
const script = insertScript(url, 'true');
script.onload = resolve;
script.onerror = reject;
});
}
var deps = [];
if (!('customElements' in window)) {
deps.push(downloadAsync('/url/of/polyfill.js'));
// if you need more than 1 polyfill add more deps.push
}
Promise.all(deps).then(() => {
insertScript('/static/elements/my-element.js');
});
答
推荐的方法是总是load the complete polyfill(仅限82 ko)。
<script src="/path/to/webcomponents-lite.js"></script>
<script src="/static/elements/my-element.js"></script>
由于脚本加载是同步的,所以polyfill和自定义元素将以正确的顺序加载。
如果你想只支持Firefox和边缘,你可以替换webcomponents-lite.js通过webcomponents-SD-ce.js(64 KO),但你将获得只在大多数情况下几毫秒。
或者,和非常糟糕的网络,你可以use the webcomponents-loader.js(4 KO)将执行特征检测与荷载为您服务。
您也可以缩小它,甚至更好,直接在您的主页面插入其内容,以节省一个请求的往返延迟。
强迫82kb/64kb给每个人,不管他们是否需要它,这是我不想做的事情。我尝试使用'webcomponents-loader.js',但我的自定义元素似乎在实际的polyfill运行之前运行(动态加载的脚本似乎是运行异步?)。 –
是的,它是异步的,因此您应该等待链接中所述的WebComponentsReady事件 – Supersharp