所谓 File Prefetching 就是在一个页面加载成功后,默默去预加载后续可能会被访问到的页面的资源。前端资源预加载其实没啥新鲜的,我们倒腾这个事情的过程却是很有有意思也很有启发性。
第一个版本,简单粗暴有点痛
1、建一个独立的页面,里面索引了各种需要预加载的css、js,代码类似下面这样。
<html> <head> <link rel="stylesheet" href="//su.yzcdn.cn/v2/build_css/stylesheets/wap/showcase_d0fbaaef124a8691398704216ccd469a.css"> ...其他需要预加载的css</head><body> <script src="//su.yzcdn.cn/v2/build/wap/common_08b03c7826.js" onerror="_cdnFallback(this)"></script> ...其他需要预加载的js</body> </html>
2、 在每个页面加入一个iframe(一般通过base模板统一加),这样每个页面打开的时候都会加载上面这个页面。假设上面的页面的url是 https://xxx.com/common/prefetching.html 那么我们每个页面底部都有这么一行代码:
<iframe src="https://youzan.com/common/prefetching.html" sytle="display:none;"></iframe>
验证
要验证某个file prefetching的方案是否真的有效,无非就是以下几步: (假设A页面使用了 showcase_d0fbaaef124a8691398704216ccd469a.css ,而B页面不会)
- 让chrome终端打开的时候cache功能依旧有效
- 清空所有本地cache
- 打开B页面,在控制台Networking里看prefetching.html以及附属的资源文件是否被下载了
- 打开A页面,注意:是在地址栏里输入A的网址然后回车,不要打开A页面后习惯性地按Command/Ctrl+R来刷新,不出意外,我们会看到如下图这样的结果: 这说明,这2个css文件是从cache里读的。如果Command/Ctrl+R来刷新页面,我们会看到这样的结果: 两者的差别是,Command/Ctrl+R的时候,浏览器会从cache里找该静态文件,如果找到了,会根据上次请求这个文件时得到的 cache-control 信息判断该静态文件是否已经过期了,如果没有,会以 if-modified-since 、 Etag 等信息作为 request headers 向服务器请求这个文件,服务器如果认为文件没有变过,会返回Http code为304,浏览器于是直接读cache。具体不展开啦,可以看 《HTTP caching 》 和 《Understanding HTTP/304 Responses》 。
操作指引:
让chrome终端打开的时候cache功能依旧有效 :Chrome终端的配置里把 Disable cache (while DevTools is open) 的勾选去掉
清空所有cache :地址栏里输入 chrome://settings/clearBrowserData 打开后勾上 Cached images and files 点 Clear browsing data
查看浏览器当前cache的资源列表 : chrome://cache/
第二个版本,依样画葫芦
目前看来,上面这个 File Prefeching 的方案是有效的。不过这种是最简陋的试验版,存在几个问题:
- prefetching.html 里的js会被执行,然后不可避免地会有一堆js错误 —— 看着难受~
- 通过iframe 加载 prefetching.html 会影响到当前页面相关资源的加载速度
- 每次打开页面都会加载一次 prefetching.html,虽然里面的静态文件都已经在第一次打开的时候被cache住了不会重复下载,但无谓多一个请求终究是没必要。
于是,我们上线使用的版本是这样的:
1、有一段每个页面都会被执行到的js:
// 打开一个iframe,下载之后页面可能需要的js/csssetTimeout(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小时打开一次iframe return; } var iframe = $('<iframe>').css('display', 'none'); iframe .attr('src', 'https://youzan.com/common/prefetching.html') .appendTo(document.body); try { window.localStorage.setItem('staticIframeOpenTime', nowTime); } catch (e) {}}, 3000);// 延时3秒钟加载prefetching.html
2、prefetching.html 里的资源想办法让他下载但不执行,基本上都是把这些css/js文件当做其他类型的文件来加载,最后参照了 《Preload CSS/JavaScript without execution》 这篇文章,prefetching.html 中加载js文件的代码大概是这样的:
<script type="text/javascript"> window.onload = function () { var i = 0, max = 0, o = null, preload = [ '需要预加载的文件路径' ], isIE = navigator.appName.indexOf('Microsoft') === 0; for (i = 0, max = preload.length; i < max; i += 1) { if (isIE) { new Image().src = preload[i]; continue; } // firefox不兼容 new Image().src 这种方式,所以除了IE都借用 object 来加载 o = document.createElement('object'); o.data = preload[i]; o.width = 0; o.height = 0; document.body.appendChild(o); } };</script>
通过 对预加载的js文件只下载不执行 、 延时加载prefetching.html 、 借助localstorage的记录一天只加载一次prefetching.html ,基本上解决了版本一的3个问题。
效果和问题
移动页面全站上线后,平均loaded时间减少了0.15s,首屏时间没有数据,不过收益应该是可观的
不过,这个版本上线后,我们发现页面在prefetching的时候会假死,最后定位到是因为object加载js导致的(具体为什么会这样还没细究),考虑到我们主要的页面都是在手机端访问的,基本上都是webkit内核(Image的方式在firefox中不兼容也不甚关系),所以我们决定改用Image来加载所有JS。
第三个版本,完美
这个版本除了解决第二个版本的假死问题,还加入了dns-prefetch,关于这部分的背景和思路可以参考我另外一篇文章: 《预加载系列一:DNS Prefetching 的正确使用姿势》 。
<!DOCTYPE html> <html> <head> <?php // dns prefething here ?> <link rel="dns-prefetch" href="//youzan.com/"> ... <?php // css prefething here ?> <link rel="stylesheet" href="//su.yzcdn.cn/v2/build_css/stylesheets/wap/showcase_d0fbaaef124a8691398704216ccd469a.css"> ...</head> <body> <?php // js prefething here ?> <script type="text/javascript"> (function(){ window.onload = function () { var i = 0, max = 0, preloadJs = [ 'js文件路径', ... ]; for (i = 0, max = preloadJs.length; i < max; i += 1) { new Image().src = preloadJs[i]; } }; })(); </script></body> </html>
上线后,丝丝润滑无痛无痒,完美
第四个版本,再进一步,可以做更多
注意哦,重点来咯! 尽早加载css是减少首屏时间的关键( 引申阅读 ), 直接把css inline到html里 是个不错的方案。但是,这种方案的缺点是无法充分利用浏览器缓存。所以,我们尝试在现有的File Prefetching 的基础上,再进一步,让首次访问足够快(用css line),后续访问又能利用起浏览器缓存。
我们对一部分重点页面的css文件改用类似加载js的方式去加载,并在加载成功的回调里加一条cookie记录标示该css文件已经被下载。这样在后端输出html的时候,可以根据cookie的信息知道这几个css文件是不是已经在浏览器里cache住了。如果是则正常输出一个
标签。如果不是,说明用户是第一次访问这个页面,则直接把css文件的内容inline到html里以求最快出首屏。当然,也会出现从cookie上看客户端已经cache了某个css文件,但实际上没有的情况,由于这种情况下html里输出的还是一个link标签,并不会影响正常的流程。
相关代码大概是这样的,需要的朋友可以参考下:
var loadCss = function(key, url) { var image = new Image(); var date = new Date(); date.setTime(+date + 1 * 86400000); // 因为下载的不是图片,实际触发的是onerror事件 image.onload = image.onerror = function () { document.cookie = key + '=' + url.slice(url.indexOf('build_css')) + ';path=/;domain=.koudaitong.com;expires=' + date.toGMTString(); }; image.src = url;}preloadCss = { key1: '文件路径', key2: '文件路径2' ...}for (var key in preloadCss) { loadCss(key, preloadCss[key]);}
总结
在做 File Prefetching 的过程当中,每一个版本的优化都是不同的人在做的:
A起了个头 ->
B改进到能上线的标准 ->
发现有问题,C改进了它 ->
D又在这个基础上做出了最后一个版本。
这种感觉非常好:)
TODO
- 其实还有一类资源可以加到这个prefetching.html里,那就是常用的图片,不过我们还没这么做。
- 我们现在全部移动web页只使用一个prefetching.html,并还没有针对不同的条件进行针对性的的prefetching。

要構建一個功能強大且用戶體驗良好的網站,僅靠HTML是不夠的,還需要以下技術:JavaScript賦予網頁動態和交互性,通過操作DOM實現實時變化。 CSS負責網頁的樣式和佈局,提升美觀度和用戶體驗。現代框架和庫如React、Vue.js和Angular,提高開發效率和代碼組織結構。

布爾屬性是HTML中的特殊屬性,不需要值即可激活。 1.布爾屬性通過存在與否控制元素行為,如disabled禁用輸入框。 2.它們的工作原理是瀏覽器解析時根據屬性的存在改變元素行為。 3.基本用法是直接添加屬性,高級用法可通過JavaScript動態控制。 4.常見錯誤是誤以為需要設置值,正確寫法應簡潔。 5.最佳實踐是保持代碼簡潔,合理使用布爾屬性以優化網頁性能和用戶體驗。

HTML代碼可以通過在線驗證器、集成工具和自動化流程來確保其清潔度。 1)使用W3CMarkupValidationService在線驗證HTML代碼。 2)在VisualStudioCode中安裝並配置HTMLHint擴展進行實時驗證。 3)利用HTMLTidy在構建流程中自動驗證和清理HTML文件。

HTML、CSS和JavaScript是構建現代網頁的核心技術:1.HTML定義網頁結構,2.CSS負責網頁外觀,3.JavaScript提供網頁動態和交互性,它們共同作用,打造出用戶體驗良好的網站。

HTML的功能是定義網頁的結構和內容,其目的在於提供一種標準化的方式來展示信息。 1)HTML通過標籤和屬性組織網頁的各個部分,如標題和段落。 2)它支持內容與表現分離,提升維護效率。 3)HTML具有可擴展性,允許自定義標籤增強SEO。

HTML的未來趨勢是語義化和Web組件,CSS的未來趨勢是CSS-in-JS和CSSHoudini,JavaScript的未來趨勢是WebAssembly和Serverless。 1.HTML的語義化提高可訪問性和SEO效果,Web組件提升開發效率但需注意瀏覽器兼容性。 2.CSS-in-JS增強樣式管理靈活性但可能增大文件體積,CSSHoudini允許直接操作CSS渲染。 3.WebAssembly優化瀏覽器應用性能但學習曲線陡,Serverless簡化開發但需優化冷啟動問題。

HTML、CSS和JavaScript在Web開發中的作用分別是:1.HTML定義網頁結構,2.CSS控製網頁樣式,3.JavaScript添加動態行為。它們共同構建了現代網站的框架、美觀和交互性。

HTML的未來充滿了無限可能。 1)新功能和標準將包括更多的語義化標籤和WebComponents的普及。 2)網頁設計趨勢將繼續向響應式和無障礙設計發展。 3)性能優化將通過響應式圖片加載和延遲加載技術提升用戶體驗。


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

WebStorm Mac版
好用的JavaScript開發工具

mPDF
mPDF是一個PHP庫,可以從UTF-8編碼的HTML產生PDF檔案。原作者Ian Back編寫mPDF以從他的網站上「即時」輸出PDF文件,並處理不同的語言。與原始腳本如HTML2FPDF相比,它的速度較慢,並且在使用Unicode字體時產生的檔案較大,但支援CSS樣式等,並進行了大量增強。支援幾乎所有語言,包括RTL(阿拉伯語和希伯來語)和CJK(中日韓)。支援嵌套的區塊級元素(如P、DIV),

EditPlus 中文破解版
體積小,語法高亮,不支援程式碼提示功能

DVWA
Damn Vulnerable Web App (DVWA) 是一個PHP/MySQL的Web應用程序,非常容易受到攻擊。它的主要目標是成為安全專業人員在合法環境中測試自己的技能和工具的輔助工具,幫助Web開發人員更好地理解保護網路應用程式的過程,並幫助教師/學生在課堂環境中教授/學習Web應用程式安全性。 DVWA的目標是透過簡單直接的介面練習一些最常見的Web漏洞,難度各不相同。請注意,該軟體中

SublimeText3 英文版
推薦:為Win版本,支援程式碼提示!