quicklink
Version:
Faster subsequent page-loads by prefetching in-viewport links during idle time
2 lines (1 loc) • 3.03 kB
JavaScript
function e(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n<t;n++)r[n]=e[n];return r}function t(t,n){var r="undefined"!=typeof Symbol&&t[Symbol.iterator]||t["@@iterator"];if(r)return(r=r.call(t)).next.bind(r);if(Array.isArray(t)||(r=function(t,n){if(t){if("string"==typeof t)return e(t,n);var r={}.toString.call(t).slice(8,-1);return"Object"===r&&t.constructor&&(r=t.constructor.name),"Map"===r||"Set"===r?Array.from(t):"Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r)?e(t,n):void 0}}(t))||n){r&&(t=r);var o=0;return function(){return o>=t.length?{done:!0}:{done:!1,value:t[o++]}}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function n(e,t,n,r){var o={headers:{accept:"*/*"}};return t||(o.mode="no-cors"),n&&(o.credentials="include"),o.priority=r?"high":"low",window.fetch?fetch(e,o):function(e,t){return new Promise(function(n,r,o){(o=new XMLHttpRequest).open("GET",e,o.withCredentials=t),o.setRequestHeader("Accept","*/*"),o.onload=function(){200===o.status?n():r()},o.send()})}(e,n)}var r,o=(r=document.createElement("link")).relList&&r.relList.supports&&r.relList.supports("prefetch")?function(e,t){return new Promise(function(n,r,o){(o=document.createElement("link")).rel="prefetch",o.href=e,t&&o.setAttribute("crossorigin","anonymous"),o.onload=n,o.onerror=r,document.head.append(o)})}:n,i=window.requestIdleCallback||function(e){var t=Date.now();return setTimeout(function(){e({didTimeout:!1,timeRemaining:function(){return Math.max(0,50-(Date.now()-t))}})},1)},a=new Set;function u(e,t){return Array.isArray(t)?t.some(function(t){return u(e,t)}):(t.test||t).call(t,e.href,e)}function c(e){if(void 0===e&&(e={}),window.IntersectionObserver){var n=function(e){e=e||1;var t=[],n=0;function r(){n<e&&t.length>0&&(t.shift()(),n++)}return[function(e){t.push(e)>1||r()},function(){n--,r()}]}(e.throttle||Number.Infinity),r=n[0],o=n[1],c=e.limit||Number.Infinity,f=e.origins||[location.hostname],l=e.ignores||[],d=e.timeoutFn||i,m=e.prefetchChunks,h=function(t){s(t,e.priority).then(o).catch(function(t){o(),e.onError&&e.onError(t)})},v=new IntersectionObserver(function(e){for(var n,o=function(){var e=n.value,t=e.isIntersecting,o=e.target;if(!t)return 1;v.unobserve(o),a.size<c&&r(function(){m?m(o,h):h(o.href)})},i=t(e);!(n=i()).done;)o()});return d(function(){for(var n,r=t((e.el||document).querySelectorAll("a[href]"));!(n=r()).done;){var o=n.value;f.length&&!f.includes(o.hostname)||u(o,l)||v.observe(o)}},{timeout:e.timeout||2e3}),function(){a.clear(),v.disconnect()}}}function s(e,t){var r=navigator.connection;return r?r.saveData?Promise.reject(new Error("Cannot prefetch, Save-Data is enabled")):/2g/.test(r.effectiveType)?Promise.reject(new Error("Cannot prefetch, network conditions are poor")):Promise.all([e].flat().map(function(e){return a.has(e)?[]:(a.add(e),(t?n:o)(new URL(e,location.href).toString()))})):Promise.resolve()}export{c as listen,s as prefetch};