目录
第一个版本,简单粗暴有点痛
验证
操作指引:
第二个版本,依样画葫芦
效果和问题
第三个版本,完美
上线后,丝丝润滑无痛无痒,完美
第四个版本,再进一步,可以做更多
总结
TODO
首页 web前端 html教程 预加载系列二:让File Prefetching丝丝润滑无痛无痒_html/css_WEB-ITnose

预加载系列二:让File Prefetching丝丝润滑无痛无痒_html/css_WEB-ITnose

Jun 24, 2016 am 11:29 AM

所谓 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页面不会)

  1. 让chrome终端打开的时候cache功能依旧有效
  2. 清空所有本地cache
  3. 打开B页面,在控制台Networking里看prefetching.html以及附属的资源文件是否被下载了
  4. 打开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 的方案是有效的。不过这种是最简陋的试验版,存在几个问题:

  1. prefetching.html 里的js会被执行,然后不可避免地会有一堆js错误 —— 看着难受~
  2. 通过iframe 加载 prefetching.html 会影响到当前页面相关资源的加载速度
  3. 每次打开页面都会加载一次 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

  1. 其实还有一类资源可以加到这个prefetching.html里,那就是常用的图片,不过我们还没这么做。
  2. 我们现在全部移动web页只使用一个prefetching.html,并还没有针对不同的条件进行针对性的的prefetching。
本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

HTML容易为初学者学习吗? HTML容易为初学者学习吗? Apr 07, 2025 am 12:11 AM

HTML适合初学者学习,因为它简单易学且能快速看到成果。1)HTML的学习曲线平缓,易于上手。2)只需掌握基本标签即可开始创建网页。3)灵活性高,可与CSS和JavaScript结合使用。4)丰富的学习资源和现代工具支持学习过程。

HTML,CSS和JavaScript的角色:核心职责 HTML,CSS和JavaScript的角色:核心职责 Apr 08, 2025 pm 07:05 PM

HTML定义网页结构,CSS负责样式和布局,JavaScript赋予动态交互。三者在网页开发中各司其职,共同构建丰富多彩的网站。

了解HTML,CSS和JavaScript:初学者指南 了解HTML,CSS和JavaScript:初学者指南 Apr 12, 2025 am 12:02 AM

WebDevelovermentReliesonHtml,CSS和JavaScript:1)HTMLStructuresContent,2)CSSStyleSIT和3)JavaScriptAddSstractivity,形成thebasisofmodernWebemodernWebExexperiences。

HTML中起始标签的示例是什么? HTML中起始标签的示例是什么? Apr 06, 2025 am 12:04 AM

AnexampleOfAstartingTaginHtmlis,beginSaparagraph.startingTagSareEssentialInhtmlastheyInitiateEllements,defiteTheeTheErtypes,andarecrucialforsstructuringwebpages wepages webpages andConstructingthedom。

Gitee Pages静态网站部署失败:单个文件404错误如何排查和解决? Gitee Pages静态网站部署失败:单个文件404错误如何排查和解决? Apr 04, 2025 pm 11:54 PM

GiteePages静态网站部署失败:404错误排查与解决在使用Gitee...

网页批注如何实现Y轴位置的自适应布局? 网页批注如何实现Y轴位置的自适应布局? Apr 04, 2025 pm 11:30 PM

网页批注功能的Y轴位置自适应算法本文将探讨如何实现类似Word文档的批注功能,特别是如何处理批注之间的间�...

HTML,CSS和JavaScript:Web开发人员的基本工具 HTML,CSS和JavaScript:Web开发人员的基本工具 Apr 09, 2025 am 12:12 AM

HTML、CSS和JavaScript是Web开发的三大支柱。1.HTML定义网页结构,使用标签如、等。2.CSS控制网页样式,使用选择器和属性如color、font-size等。3.JavaScript实现动态效果和交互,通过事件监听和DOM操作。

如何用CSS3和JavaScript实现图片点击后周围图片散开并放大效果? 如何用CSS3和JavaScript实现图片点击后周围图片散开并放大效果? Apr 05, 2025 am 06:15 AM

实现图片点击后周围图片散开并放大效果许多网页设计中,需要实现一种交互效果:点击某张图片,使其周围的...

See all articles