摘要:文件路徑,上線后,絲絲潤(rùn)滑無(wú)痛無(wú)癢,完美第四個(gè)版本,可以做更多注意哦,重點(diǎn)來(lái)咯盡早加載是減少首屏?xí)r間的關(guān)鍵引申閱讀,直接把到里是個(gè)不錯(cuò)的方案。
第一個(gè)版本,簡(jiǎn)單粗暴有點(diǎn)痛所謂 File Prefetching 就是在一個(gè)頁(yè)面加載成功后,默默去預(yù)加載后續(xù)可能會(huì)被訪問(wèn)到的頁(yè)面的資源。
前端資源預(yù)加載其實(shí)沒(méi)啥新鮮的,我們倒騰這個(gè)事情的過(guò)程卻是很有有意思也很有啟發(fā)性。
1、建一個(gè)獨(dú)立的頁(yè)面,里面索引了各種需要預(yù)加載的css、js,代碼類似下面這樣。
...其他需要預(yù)加載的css ...其他需要預(yù)加載的js
2、 在每個(gè)頁(yè)面加入一個(gè)iframe(一般通過(guò)base模板統(tǒng)一加),這樣每個(gè)頁(yè)面打開(kāi)的時(shí)候都會(huì)加載上面這個(gè)頁(yè)面。假設(shè)上面的頁(yè)面的url是 https://xxx.com/common/prefetching.html 那么我們每個(gè)頁(yè)面底部都有這么一行代碼:
如何驗(yàn)證要驗(yàn)證某個(gè)file prefetching的方案是否真的有效,無(wú)非就是以下幾步:
(假設(shè)A頁(yè)面使用了showcase_d0fbaaef124a8691398704216ccd469a.css,而B(niǎo)頁(yè)面不會(huì))
讓chrome終端打開(kāi)的時(shí)候cache功能依舊有效
清空所有本地cache
打開(kāi)B頁(yè)面,在控制臺(tái)Networking里看prefetching.html以及附屬的資源文件是否被下載了
打開(kāi)A頁(yè)面,注意:是在地址欄里輸入A的網(wǎng)址然后回車,不要打開(kāi)A頁(yè)面后習(xí)慣性地按Command/Ctrl+R來(lái)刷新,不出意外,我們會(huì)看到如下圖這樣的結(jié)果:
這說(shuō)明,這2個(gè)css文件是從cache里讀的。如果Command/Ctrl+R來(lái)刷新頁(yè)面,我們會(huì)看到這樣的結(jié)果:
兩者的差別是,Command/Ctrl+R的時(shí)候,瀏覽器會(huì)從cache里找該靜態(tài)文件,如果找到了,會(huì)根據(jù)上次請(qǐng)求這個(gè)文件時(shí)得到的cache-control信息判斷該靜態(tài)文件是否已經(jīng)過(guò)期了,如果沒(méi)有,會(huì)以 if-modified-since、Etag 等信息作為 request headers 向服務(wù)器請(qǐng)求這個(gè)文件,服務(wù)器如果認(rèn)為文件沒(méi)有變過(guò),會(huì)返回Http code為304,瀏覽器于是直接讀cache。具體不展開(kāi)啦,可以看 [《HTTP caching
》](https://developers.google.com/web/fundam... 和 《Understanding HTTP/304 Responses》。
讓chrome終端打開(kāi)的時(shí)候cache功能依舊有效:Chrome終端的配置里把Disable cache (while DevTools is open)的勾選去掉
清空所有cache:地址欄里輸入 chrome://settings/clearBrowserData 打開(kāi)后勾上 Cached images and files 點(diǎn) Clear browsing data
查看瀏覽器當(dāng)前cache的資源列表:chrome://cache/
目前看來(lái),上面這個(gè) File Prefeching 的方案是有效的。不過(guò)這種是最簡(jiǎn)陋的試驗(yàn)版,存在幾個(gè)問(wèn)題:
prefetching.html 里的js會(huì)被執(zhí)行,然后不可避免地會(huì)有一堆js錯(cuò)誤 —— 看著難受~
通過(guò)iframe 加載 prefetching.html 會(huì)影響到當(dāng)前頁(yè)面相關(guān)資源的加載速度
每次打開(kāi)頁(yè)面都會(huì)加載一次 prefetching.html,雖然里面的靜態(tài)文件都已經(jīng)在第一次打開(kāi)的時(shí)候被cache住了不會(huì)重復(fù)下載,但無(wú)謂多一個(gè)請(qǐng)求終究是沒(méi)必要。
于是,我們上線使用的版本是這樣的:
1、有一段每個(gè)頁(yè)面都會(huì)被執(zhí)行到的js:
// 打開(kāi)一個(gè)iframe,下載之后頁(yè)面可能需要的js/css setTimeout(function() { var lastOpenTime = 0; var nowTime = (new Date()).getTime(); try { lastOpenTime = window.localStorage.getItem("staticIframeOpenTime"); } catch (e) {} if (lastOpenTime > 0 && (nowTime - lastOpenTime < 24 * 3600 * 1000)) { // 24小時(shí)打開(kāi)一次iframe return; } var iframe = $("
2、prefetching.html 里的資源想辦法讓他下載但不執(zhí)行,基本上都是把這些css/js文件當(dāng)做其他類型的文件來(lái)加載,最后參照了《Preload CSS/JavaScript without execution》這篇文章,prefetching.html 中加載js文件的代碼大概是這樣的:
通過(guò)對(duì)預(yù)加載的js文件只下載不執(zhí)行、延時(shí)加載prefetching.html、借助localstorage的記錄一天只加載一次prefetching.html,基本上解決了版本一的3個(gè)問(wèn)題。
效果和問(wèn)題移動(dòng)頁(yè)面全站上線后,平均loaded時(shí)間減少了0.15s,首屏?xí)r間沒(méi)有數(shù)據(jù),不過(guò)收益應(yīng)該是可觀的
不過(guò),這個(gè)版本上線后,我們發(fā)現(xiàn)頁(yè)面在prefetching的時(shí)候會(huì)假死,最后定位到是因?yàn)閛bject加載js導(dǎo)致的(具體為什么會(huì)這樣還沒(méi)細(xì)究),考慮到我們主要的頁(yè)面都是在手機(jī)端訪問(wèn)的,基本上都是webkit內(nèi)核(Image的方式在firefox中不兼容也不甚關(guān)系),所以我們決定改用Image來(lái)加載所有JS。
第三個(gè)版本,完美這個(gè)版本除了解決第二個(gè)版本的假死問(wèn)題,還加入了dns-prefetch,關(guān)于這部分的背景和思路可以參考我另外一篇文章:《預(yù)加載系列一:DNS Prefetching 的正確使用姿勢(shì)》。
... ...
上線后,絲絲潤(rùn)滑無(wú)痛無(wú)癢,完美
第四個(gè)版本,可以做更多注意哦,重點(diǎn)來(lái)咯!
盡早加載css是減少首屏?xí)r間的關(guān)鍵(引申閱讀),直接把css inline到html里是個(gè)不錯(cuò)的方案。但是,這種方案的缺點(diǎn)是無(wú)法充分利用瀏覽器緩存。所以,我們嘗試在現(xiàn)有的File Prefetching 的基礎(chǔ)上,再進(jìn)一步,讓首次訪問(wèn)足夠快(用css line),后續(xù)訪問(wèn)又能利用起瀏覽器緩存。
我們對(duì)一部分重點(diǎn)頁(yè)面的css文件改用類似加載js的方式去加載,并在加載成功的回調(diào)里加一條cookie記錄標(biāo)示該css文件已經(jīng)被下載。這樣在后端輸出html的時(shí)候,可以根據(jù)cookie的信息知道這幾個(gè)css文件是不是已經(jīng)在瀏覽器里cache住了。如果是則正常輸出一個(gè)標(biāo)簽。如果不是,說(shuō)明用戶是第一次訪問(wèn)這個(gè)頁(yè)面,則直接把css文件的內(nèi)容inline到html里以求最快出首屏。當(dāng)然,也會(huì)出現(xiàn)從cookie上看客戶端已經(jīng)cache了某個(gè)css文件,但實(shí)際上沒(méi)有的情況,由于這種情況下html里輸出的還是一個(gè)link標(biāo)簽,并不會(huì)影響正常的流程。
相關(guān)代碼大概是這樣的,需要的朋友可以參考下:
var loadCss = function(key, url) { var image = new Image(); var date = new Date(); date.setTime(+date + 1 * 86400000); // 因?yàn)橄螺d的不是圖片,實(shí)際觸發(fā)的是onerror事件 image.onload = image.onerror = function () { document.cookie = key + "=" + url.slice(url.indexOf("build_css")) + ";path=/;domain=.youzan.com;expires=" + date.toGMTString(); }; image.src = url; } preloadCss = { key1: "文件路徑", key2: "文件路徑2" ... } for (var key in preloadCss) { loadCss(key, preloadCss[key]); }總結(jié)
在做 File Prefetching 的過(guò)程當(dāng)中,每一個(gè)版本的優(yōu)化都是不同的人在做的:
A起了個(gè)頭 ->
B改進(jìn)到能上線的標(biāo)準(zhǔn) ->
發(fā)現(xiàn)有問(wèn)題,C改進(jìn)了它 ->
D又在這個(gè)基礎(chǔ)上做出了最后一個(gè)版本。
這種感覺(jué)非常好:)
TODO其實(shí)還有一類資源可以加到這個(gè)prefetching.html里,那就是常用的圖片,不過(guò)我們還沒(méi)這么做。
現(xiàn)在我們有贊全部移動(dòng)web頁(yè)只使用一個(gè)prefetching.html,并還沒(méi)有針對(duì)不同的條件進(jìn)行針對(duì)性的的prefetching。
本文首發(fā)于我的
SegmentFault專欄:https://segmentfault.com/a/1190000004189...
個(gè)人技術(shù)博客:http://delai.me/code/file-frefetching/
轉(zhuǎn)載請(qǐng)注明出處
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/61759.html
摘要:前端日?qǐng)?bào)精選和實(shí)現(xiàn)直接當(dāng)前頁(yè)預(yù)覽手淘互動(dòng)動(dòng)效的探索白話原型和原型鏈源碼解析瀏覽器前端優(yōu)化中文第期深入理解中的動(dòng)畫演示,提高你的網(wǎng)頁(yè)開(kāi)發(fā)技能知乎專欄實(shí)戰(zhàn)一概覽工作機(jī)制第部分迷津欲有問(wèn)把賣了眾成翻譯代理程序?qū)崿F(xiàn)復(fù)制集搭建及抓包 2017-08-24 前端日?qǐng)?bào) 精選 iframe和HTML5 blob實(shí)現(xiàn)JS,CSS,HTML直接當(dāng)前頁(yè)預(yù)覽手淘互動(dòng)動(dòng)效的探索白話原型和原型鏈React 源碼解...
摘要:錯(cuò)過(guò)一周的優(yōu)質(zhì)內(nèi)容,不要再錯(cuò)過(guò)周一的快速回顧寒潮來(lái)得出乎意料,手腳,一遍聽(tīng)著史詩(shī)巨著張士超你到底把我家鑰匙放哪里了,一邊將優(yōu)質(zhì)內(nèi)容進(jìn)行整理一周咨詢當(dāng)技術(shù)成為一種武器翻譯組一周簡(jiǎn)訊跟著輪子哥造輪子基本概念二排版前端名一前端遠(yuǎn)程調(diào)試德來(lái)預(yù)加載 錯(cuò)過(guò)一周的優(yōu)質(zhì)內(nèi)容,不要再錯(cuò)過(guò)周一的快速回顧 寒潮來(lái)得出乎意料,dong手dong腳,一遍聽(tīng)著史詩(shī)巨著《張士超你到底把我家鑰匙放哪里了》,一邊將優(yōu)質(zhì)...
摘要:錯(cuò)過(guò)一周的優(yōu)質(zhì)內(nèi)容,不要再錯(cuò)過(guò)周一的快速回顧寒潮來(lái)得出乎意料,手腳,一遍聽(tīng)著史詩(shī)巨著張士超你到底把我家鑰匙放哪里了,一邊將優(yōu)質(zhì)內(nèi)容進(jìn)行整理一周咨詢當(dāng)技術(shù)成為一種武器翻譯組一周簡(jiǎn)訊跟著輪子哥造輪子基本概念二排版前端名一前端遠(yuǎn)程調(diào)試德來(lái)預(yù)加載 錯(cuò)過(guò)一周的優(yōu)質(zhì)內(nèi)容,不要再錯(cuò)過(guò)周一的快速回顧 寒潮來(lái)得出乎意料,dong手dong腳,一遍聽(tīng)著史詩(shī)巨著《張士超你到底把我家鑰匙放哪里了》,一邊將優(yōu)質(zhì)...
閱讀 746·2021-11-11 16:54
閱讀 3066·2021-09-26 09:55
閱讀 2019·2021-09-07 10:20
閱讀 1211·2019-08-30 10:58
閱讀 1057·2019-08-28 18:04
閱讀 710·2019-08-26 13:57
閱讀 3599·2019-08-26 13:45
閱讀 1164·2019-08-26 11:42