Rezept für bergamottemarmelade
connection.effectiveType.includes('2g') if (!isNavigatorConnectionSaveDataEnabled && !isNavigatorConnectionLike2g) { if (intensity == "viewport") { if (document.documentElement.clientWidth * document.documentElement.clientHeight < 450000) { useViewport = true // Smartphones haben am ehesten eine langsame Verbindung, und // ihre geringe Bildschirmgröße begrenzt die Anzahl der Links (und damit // die Serverlast). // // Faltbare Telefone (die ab 2023 teuer sind), Tablets und PCs // haben im Allgemeinen eine anständige Verbindung und einen großen Bildschirm mit // mehr Links, die den Server stärker belasten würden.
iPhone 14 Pro Max (gewünscht): 430?932 = 400?760 // Samsung Galaxy S22 Ultra mit Displaygröße auf 80% eingestellt (gewünscht): // 450?965 = 434?250 // Kleines Tablet (nicht wollen): 600?960 = 576.000 // Diese Zahl ist die virtuelle Bildschirmgröße, der Viewport (verwendet für // die obige Prüfung) wird mit der Benutzeroberfläche des Browsers kleiner. } } else if (intensity == "viewport-all") { useViewport = true } } } else { const milliseconds = parseInt(intensity) if (!isNaN(milliseconds)) { _delayOnHover = Millisekunden } } } if (!useMousedownOnly) { document.addEventListener('touchstart', touchstartListener, eventListenersOptions) } if (!useMousedown) { document.addEventListener('mouseover', mouseoverListener, eventListenersOptions) } else if (!mousedownShortcut) { document.addEventListener('mousedown', mousedownListener, eventListenersOptions) } if (mousedownShortcut) { document.addEventListener('mousedown', mousedownShortcutListener, eventListenersOptions) } if (useViewport) { let requestIdleCallbackOrFallback = window.requestIdleCallback // Safari wird ab 16.3 nicht unterstützt: https://webkit.org/b/164193 if (!requestIdleCallbackOrFallback) { requestIdleCallbackOrFallback = (callback) => { callback() // Ein intelligenterer Fallback wie setTimeout wird nicht verwendet, da Geräte, die // möglicherweise möglicherweise für einen Safari in Frage kommen, nicht verwendet werden Die Version, die Prefetch // unterstützt, wird sehr leistungsfähig sein.
Die schwächsten Geräte, die in Frage kommen könnten, sind das iPad 2017 und das MacBook 2016. } } requestIdleCallbackOrFallback(function observeIntersection() { const intersectionObserver = new IntersectionObserver((einträge) => { entries.forEach((entry) => { if (entry.isIntersecting) { const anchorElement = entry.target intersectionObserver.unobserve(anchorElement) preload(anchorElement.href) } }) }) document.querySelectorAll('a').forEach((anchorElement) => { if (isPreloadable(anchorElement)) { intersectionObserver.observe(anchorElement) } }) }, { timeout: 1500, }) } } function touchstartListener(event) { _lastTouchTimestamp = performance.now() // Chrome auf Android löst Mouseover vor Touchcancel aus, also // '_lastTouchTimestamp' muss bei Touchstart zugewiesen werden, um gemessen zu werden // bei Mouseover.
const anchorElement = event.target.closest('a') if (!isPreloadable(anchorElement)) { return } preload(anchorElement.href, 'high') } function mouseoverListener(event) { if (performance.now() - _lastTouchTimestamp < DELAY_TO_NOT_BE_CONSIDERED_A_TOUCH_INITIATED_ACTION) { return } if (!(' closest' in event.target)) { return // Ohne diese Prüfung wird manchmal ein Fehler event.target.closest is not a function geworfen, aus unbekannten Gründen // Dieser Fehler bedeutet, dass 'event.target' nicht undefiniert ist.
Meine beste Vermutung ist, dass es das Dokument ist. Details könnte aus dem Auslösen eines solchen Fehlers gewonnen werden: //throw new TypeError('instant.page non-element event target: timeStamp=${~~event.timeStamp}, type=${event.type}, typeof=${typeof event.target}, nodeType=${event.target.nodeType}, nodeName=${event.target.nodeName}, viewport=${innerWidth}x${innerHeight}, coords=${event.clientX}x${event.clientY}, scroll=${scrollX}x${scrollY}') } const anchorElement = event.target.closest('a') if (!isPreloadable(anchorElement)) { return } anchorElement.
addEventListener('mouseout', mouseoutListener, {passive: true}) _mouseoverTimer = setTimeout(() => { preload(anchorElement.href, 'high') _mouseoverTimer = undefined }, _delayOnHover) } function mousedownListener(event) { const anchorElement = event.target.closest('a') if (!isPreloadable(anchorElement)) { return } preload(anchorElement.href, 'high') } function mouseoutListener(event) { if (event.relatedTarget && event.target.closest('a') == event.relatedTarget.closest('a')) { return } if (_mouseoverTimer) { clearTimeout(_mouseoverTimer) _mouseoverTimer = undefined } } function mousedownShortcutListener(event) { if (performance.now() - _lastTouchTimestamp < DELAY_TO_NOT_BE_CONSIDERED_A_TOUCH_INITIATED_ACTION) { return } const anchorElement = event.target.closest('a') if (event.which > 1 || event.metaKey || event.ctrlKey) { return } if (!anchorElement) { return } anchorElement.addEventListener('click', function (event) { if (event.detail == 1337) { return } event.preventDefault() }, {capture: true, passive: false, once: true}) const customEvent = new MouseEvent('click', {view: window, bubbles: true, cancelable: false, detail: 1337}) anchorElement.dispatchEvent(customEvent) } function isPreloadable(anchorElement) { if (!anchorElement || !anchorElement.href) { return } //Jacob: Custom blacklist by config magento 2 // blockiere alle Blacklist-URLs if (blackListUrls && anchorElement.href.match(blackListUrls)) { return false; } //Jacob: Benutzerdefinierte Whitelist von config magento 2 // alle URLs außer Whitelist-URLs blockieren if (whiteListUrls && !anchorElement.href.match(whiteListUrls)) { return false; } if (_useWhitelist && !(' instant' in anchorElement.dataset)) { return } if (anchorElement.origin != location.origin) { let allowed = _allowExternalLinks || 'instant' in anchorElement.dataset if (!allowed || !_chromiumMajorVersionInUserAgent) { // Nur Chromium: siehe Kommentar zur restriktiven Prefetch-Rückgabe } } if (![' http:', 'https:'].includes(anchorElement.protocol)) { return } if (anchorElement.protocol == 'http:' && location.protocol == 'https:') { return } if (!_allowQueryString && anchorElement.search && !(' instant' in anchorElement.dataset)) { return } if (anchorElement.hash && anchorElement.pathname + anchorElement.search == location.pathname + location.search) { return } if ('noInstant' in anchorElement.dataset) { return } return true } function preload(url, fetchPriority = 'auto') { if (_preloadedList.has(url)) { return } const linkElement = document.createElement('link') linkElement.rel = 'prefetch' linkElement.href = url linkElement.fetchPriority = fetchPriority // Standardmäßig wird ein Prefetch mit einer niedrigen Priorität geladen.
// Wenn eine faire Chance besteht, dass dieser Prefetch in naher Zukunft (= nach einem Touch-/Mausereignis) verwendet wird, hilft es // eine hohe Priorität zu geben // Die Seite wird schneller geladen, falls andere Ressourcen geladen werden. Es implizit zu priorisieren bedeutet, jede andere Ressource // die auf der Seite geladen wird, zu depriorisieren. linkElement.as = 'document' // as=document ist nur Chromium-fähig und ermöglicht es, Cross-Origin-Prefetches // für die Navigation nutzbar zu machen.
Sie nennen es restriktiven Prefetch und beabsichtigen, es zu entfernen: https://crbug.com/1352371 // // Dieses Dokument des Chrome-Teams vom 10.08.2022 // https://docs.google.com/document/d/1x232KJUIwIf-k08vpNfV85sVCRHkAxldfuIA5KOqi6M // behauptet (ich habe es nicht getestet), dass der Daten- und Batteriesparmodus sowie // die Einstellung zum Deaktivieren des Preloadings den restriktiven Prefetch nicht deaktivieren, // im Gegensatz zu regulärem Prefetch.
Das ist gut für das Prefetching bei einem Touch/Mouse // Event, könnte aber schlecht sein, wenn jeder Link im Viewport vorab abgerufen wird. document.head.appendChild(linkElement) _preloadedList.add(url) } }; events.forEach(type => window.addEventListener(type, loadPagePreload, {once: true, passive: true})) })(['touchstart', 'mouseover', 'wheel', 'scroll', 'keydown'])