목차
第一个版本,简单粗暴有点痛
验证
操作指引:
第二个版本,依样画葫芦
效果和问题
第三个版本,完美
上线后,丝丝润滑无痛无痒,完美
第四个版本,再进一步,可以做更多
总结
TODO
웹 프론트엔드 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 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

AI Hentai Generator

AI Hentai Generator

AI Hentai를 무료로 생성하십시오.

인기 기사

R.E.P.O. 에너지 결정과 그들이하는 일 (노란색 크리스탈)
3 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 최고의 그래픽 설정
3 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 아무도들을 수없는 경우 오디오를 수정하는 방법
3 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25 : Myrise에서 모든 것을 잠금 해제하는 방법
4 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌

뜨거운 도구

메모장++7.3.1

메모장++7.3.1

사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전

SublimeText3 중국어 버전

중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

드림위버 CS6

드림위버 CS6

시각적 웹 개발 도구

SublimeText3 Mac 버전

SublimeText3 Mac 버전

신 수준의 코드 편집 소프트웨어(SublimeText3)

& lt; Progress & Gt의 목적은 무엇입니까? 요소? & lt; Progress & Gt의 목적은 무엇입니까? 요소? Mar 21, 2025 pm 12:34 PM

이 기사는 HTML & lt; Progress & Gt에 대해 설명합니다. 요소, 그 목적, 스타일 및 & lt; meter & gt의 차이; 요소. 주요 초점은 & lt; progress & gt; 작업 완료 및 & lt; meter & gt; Stati의 경우

& lt; datalist & gt의 목적은 무엇입니까? 요소? & lt; datalist & gt의 목적은 무엇입니까? 요소? Mar 21, 2025 pm 12:33 PM

이 기사는 HTML & LT; Datalist & GT에 대해 논의합니다. 자동 완성 제안을 제공하고, 사용자 경험을 향상시키고, 오류를 줄임으로써 양식을 향상시키는 요소. 문자 수 : 159

& lt; meter & gt의 목적은 무엇입니까? 요소? & lt; meter & gt의 목적은 무엇입니까? 요소? Mar 21, 2025 pm 12:35 PM

이 기사는 HTML & lt; meter & gt에 대해 설명합니다. 범위 내에 스칼라 또는 분수 값을 표시하는 데 사용되는 요소 및 웹 개발의 일반적인 응용 프로그램. & lt; meter & gt; & lt; Progress & Gt; 그리고 Ex

HTML5의 크로스 브라우저 호환성에 대한 모범 사례는 무엇입니까? HTML5의 크로스 브라우저 호환성에 대한 모범 사례는 무엇입니까? Mar 17, 2025 pm 12:20 PM

기사는 HTML5 크로스 브라우저 호환성을 보장하기위한 모범 사례에 대해 논의하고 기능 감지, 점진적 향상 및 테스트 방법에 중점을 둡니다.

HTML5 양식 유효성 검사 속성을 사용하여 사용자 입력을 유효성있게하려면 어떻게합니까? HTML5 양식 유효성 검사 속성을 사용하여 사용자 입력을 유효성있게하려면 어떻게합니까? Mar 17, 2025 pm 12:27 PM

이 기사에서는 브라우저에서 직접 사용자 입력을 검증하기 위해 필요한, Pattern, Min, Max 및 Length 한계와 같은 HTML5 양식 검증 속성을 사용하는 것에 대해 설명합니다.

뷰포트 메타 태그는 무엇입니까? 반응 형 디자인에 중요한 이유는 무엇입니까? 뷰포트 메타 태그는 무엇입니까? 반응 형 디자인에 중요한 이유는 무엇입니까? Mar 20, 2025 pm 05:56 PM

이 기사는 모바일 장치의 반응 형 웹 디자인에 필수적인 Viewport Meta Tag에 대해 설명합니다. 적절한 사용이 최적의 컨텐츠 스케일링 및 사용자 상호 작용을 보장하는 방법을 설명하는 반면, 오용은 설계 및 접근성 문제로 이어질 수 있습니다.

& lt; iframe & gt; 꼬리표? 보안을 사용할 때 보안 고려 사항은 무엇입니까? & lt; iframe & gt; 꼬리표? 보안을 사용할 때 보안 고려 사항은 무엇입니까? Mar 20, 2025 pm 06:05 PM

이 기사는 & lt; iframe & gt; 외부 컨텐츠를 웹 페이지, 공통 용도, 보안 위험 및 객체 태그 및 API와 같은 대안을 포함시키는 태그의 목적.

Gitee Pages 정적 웹 사이트 배포 실패 : 단일 파일 문제를 해결하고 해결하는 방법 404 오류? Gitee Pages 정적 웹 사이트 배포 실패 : 단일 파일 문제를 해결하고 해결하는 방법 404 오류? Apr 04, 2025 pm 11:54 PM

GiteEpages 정적 웹 사이트 배포 실패 : 404 오류 문제 해결 및 해결시 Gitee ...

See all articles