摘要:等待瀏覽器空閑后執(zhí)行。使用方式參考鏈接源碼解析的入口函數(shù)接受傳入的配置參數(shù),通過(guò)函數(shù)和默認(rèn)的配置選項(xiàng)合并。然后在回調(diào)中便利傳入的數(shù)組,如果數(shù)組中的元素包含在對(duì)象中,則取消對(duì)該元素的監(jiān)視,并對(duì)該標(biāo)簽元素所對(duì)應(yīng)的資源進(jìn)行預(yù)加載。
簡(jiǎn)介
quicklink是一個(gè)js庫(kù),可以預(yù)加載出現(xiàn)在視口的網(wǎng)頁(yè)鏈接,提高用戶體驗(yàn)。它的加載過(guò)程如下:
1.檢測(cè)網(wǎng)頁(yè)中的鏈接是否出現(xiàn)在視口中,等待鏈接出現(xiàn)在視口,執(zhí)行步驟2。
2.等待瀏覽器空閑后執(zhí)行3。
3.判斷當(dāng)前的網(wǎng)絡(luò)連接是否是2G,如果是則停止執(zhí)行,如果不是2G網(wǎng)絡(luò),執(zhí)行步驟4。
4.預(yù)加載鏈接指向資源。
參考鏈接https://github.com/GoogleChro...
quicklink源碼解析quicklink的入口函數(shù)接受傳入的配置參數(shù),通過(guò)Object.assign函數(shù)和默認(rèn)的配置選項(xiàng)合并。接著執(zhí)行timeoutFn異步方法,該方法接收一個(gè)回調(diào)函數(shù),在回調(diào)中主要邏輯如下:
如果傳入的options參數(shù)中有urls屬性,則直接執(zhí)行預(yù)加載,否則通過(guò)document.querySelectorAll方法獲取所有a標(biāo)簽元素的NodeList,然后便利該元素節(jié)點(diǎn)列表,并監(jiān)視該元素節(jié)點(diǎn)
observer.observe(link);
然后判斷該a元素對(duì)象的href屬性值所屬的域名是否被允許訪問(wèn),如果被允許訪問(wèn),繼續(xù)判斷該鏈接是否應(yīng)該被忽略,判斷邏輯如下:
if (!allowed.length || allowed.includes(link.hostname)) { // If there are any filters, the link must not match any of them isIgnored(link, ignores) || toPrefetch.add(link.href); }
如果鏈接沒(méi)有被忽略,則將該節(jié)點(diǎn)的href屬性值加入到toPrefetch中
const toPrefetch = new Set(); toPrefetch.add(link.href);
總的代碼邏輯如下
export default function (options) { options = Object.assign({ timeout: 2e3, priority: false, timeoutFn: requestIdleCallback, el: document, }, options); observer.priority = options.priority; const allowed = options.origins || [location.hostname]; const ignores = options.ignores || []; options.timeoutFn(() => { // If URLs are given, prefetch them. if (options.urls) { options.urls.forEach(prefetcher); } else { // If not, find all links and use IntersectionObserver. Array.from(options.el.querySelectorAll("a"), link => { observer.observe(link); // If the anchor matches a permitted origin // ~> A `[]` or `true` means everything is allowed if (!allowed.length || allowed.includes(link.hostname)) { // If there are any filters, the link must not match any of them isIgnored(link, ignores) || toPrefetch.add(link.href); } }); } }, {timeout: options.timeout}); }檢測(cè)link出現(xiàn)在視口
上面通過(guò)observer.observe(link)監(jiān)視節(jié)點(diǎn)元素,其中observer是IntersectionObserver對(duì)象的實(shí)例,被監(jiān)聽的節(jié)點(diǎn)對(duì)象出現(xiàn)在視口時(shí),會(huì)執(zhí)行new操作時(shí)傳入的回調(diào)函數(shù),并將出現(xiàn)在視口的節(jié)點(diǎn)對(duì)象通過(guò)數(shù)組的形式傳給該回調(diào)。然后在回調(diào)中便利傳入的數(shù)組,如果數(shù)組中的元素包含在toPrefetch對(duì)象中,則取消對(duì)該元素的監(jiān)視,并對(duì)該a標(biāo)簽元素所對(duì)應(yīng)的資源進(jìn)行預(yù)加載。
const observer = new IntersectionObserver(entries => { entries.forEach(entry => { if (entry.isIntersecting) { const link = entry.target; if (toPrefetch.has(link.href)) { observer.unobserve(link); prefetcher(link.href); } } }); });異步函數(shù)實(shí)現(xiàn)
如果瀏覽器支持requestIdleCallback,則使用原生的函數(shù),如果不支持,則使用setTimeout函數(shù)做ployfill。
const requestIdleCallback = requestIdleCallback || function (cb) { const start = Date.now(); return setTimeout(function () { cb({ didTimeout: false, timeRemaining: function () { return Math.max(0, 50 - (Date.now() - start)); }, }); }, 1); }; export default requestIdleCallback;資源請(qǐng)求函數(shù)實(shí)現(xiàn)
預(yù)加載策略主要有三種
1. prefetch
function linkPrefetchStrategy(url) { return new Promise((resolve, reject) => { const link = document.createElement(`link`); link.rel = `prefetch`; link.href = url; link.onload = resolve; link.onerror = reject; document.head.appendChild(link); }); };
2.ajax加載
function xhrPrefetchStrategy(url) { return new Promise((resolve, reject) => { const req = new XMLHttpRequest(); req.open(`GET`, url, req.withCredentials=true); req.onload = () => { (req.status === 200) ? resolve() : reject(); }; req.send(); }); }
3.Fetch請(qǐng)求加載
function highPriFetchStrategy(url) { // TODO: Investigate using preload for high-priority // fetches. May have to sniff file-extension to provide // valid "as" values. In the future, we may be able to // use Priority Hints here. // // As of 2018, fetch() is high-priority in Chrome // and medium-priority in Safari. return self.fetch == null ? xhrPrefetchStrategy(url) : fetch(url, {credentials: `include`}); }網(wǎng)絡(luò)類型判斷
if (conn = navigator.connection) { // Don"t prefetch if the user is on 2G. or if Save-Data is enabled.. if ((conn.effectiveType || "").includes("2g") || conn.saveData) return; }
將上面三種預(yù)加載方法封裝成函數(shù),暴露給外部使用
const supportedPrefetchStrategy = support("prefetch") ? linkPrefetchStrategy : xhrPrefetchStrategy; function prefetcher(url, isPriority, conn) { if (preFetched[url]) { return; } if (conn = navigator.connection) { // Don"t prefetch if the user is on 2G. or if Save-Data is enabled.. if ((conn.effectiveType || "").includes("2g") || conn.saveData) return; } // Wanna do something on catch()? return (isPriority ? highPriFetchStrategy : supportedPrefetchStrategy)(url).then(() => { preFetched[url] = true; }); }; export default prefetcher;
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/100770.html
摘要:等待瀏覽器空閑后執(zhí)行。使用方式參考鏈接源碼解析的入口函數(shù)接受傳入的配置參數(shù),通過(guò)函數(shù)和默認(rèn)的配置選項(xiàng)合并。然后在回調(diào)中便利傳入的數(shù)組,如果數(shù)組中的元素包含在對(duì)象中,則取消對(duì)該元素的監(jiān)視,并對(duì)該標(biāo)簽元素所對(duì)應(yīng)的資源進(jìn)行預(yù)加載。 簡(jiǎn)介 quicklink是一個(gè)js庫(kù),可以預(yù)加載出現(xiàn)在視口的網(wǎng)頁(yè)鏈接,提高用戶體驗(yàn)。它的加載過(guò)程如下:1.檢測(cè)網(wǎng)頁(yè)中的鏈接是否出現(xiàn)在視口中,等待鏈接出現(xiàn)在視口,執(zhí)...
摘要:最后,狀態(tài)管理與同構(gòu)實(shí)戰(zhàn)這本書由我和前端知名技術(shù)大佬顏海鏡合力打磨,凝結(jié)了我們?cè)趯W(xué)習(xí)實(shí)踐框架過(guò)程中的積累和心得。 對(duì)于前端資訊比較敏感的同學(xué),可能這兩天已經(jīng)聽說(shuō)了 GoogleChromeLabs/quicklink這個(gè)項(xiàng)目:它由 Google 公司著名開發(fā)者 Addy Osmani 發(fā)起,實(shí)現(xiàn)了:在空閑時(shí)間預(yù)獲取頁(yè)面可視區(qū)域內(nèi)的鏈接,加快后續(xù)加載速度。如果你沒(méi)有聽說(shuō)過(guò) Addy Os...
摘要:作者也樹校對(duì)染陌素材也樹英布阿里云前端技術(shù)周刊由阿里云智能商業(yè)中臺(tái)體驗(yàn)技術(shù)團(tuán)隊(duì)整理編寫。如何在工作中快速成長(zhǎng)致工程師的個(gè)簡(jiǎn)單技巧工程師成長(zhǎng)干貨,全文提綱如下,圖片來(lái)自阿里技術(shù)公眾號(hào)關(guān)于我們我們是阿里云智能中臺(tái)體驗(yàn)技術(shù)團(tuán)隊(duì)。 作者:@也樹 校對(duì):@染陌 素材:@也樹、@英布 《阿里云前端技術(shù)周刊》由阿里云智能商業(yè)中臺(tái)體驗(yàn)技術(shù)團(tuán)隊(duì)整理編寫。 知乎:阿里云中臺(tái)前端/全棧團(tuán)隊(duì)專欄 Github...
閱讀 1074·2021-11-12 10:34
閱讀 999·2021-09-30 09:56
閱讀 676·2019-08-30 15:54
閱讀 2610·2019-08-30 11:14
閱讀 1476·2019-08-29 16:44
閱讀 3215·2019-08-29 16:35
閱讀 2500·2019-08-29 16:22
閱讀 2453·2019-08-29 15:39