ホームページ  >  記事  >  ウェブフロントエンド  >  プリロード シリーズ 2: ファイルのプリフェッチをスムーズかつ苦痛なく行う_html/css_WEB-ITnose

プリロード シリーズ 2: ファイルのプリフェッチをスムーズかつ苦痛なく行う_html/css_WEB-ITnose

WBOY
WBOYオリジナル
2016-06-24 11:29:041276ブラウズ

いわゆるファイルのプリフェッチとは、ページが正常にロードされた後、後でアクセスされる可能性のあるページのリソースをサイレントにプリロードすることです。実際、フロントエンド リソースのプリロードについては何も新しいことはありませんが、それを理解するプロセスは非常に興味深く、刺激的です。

最初のバージョンはシンプルで粗雑で少し面倒です

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 を追加します (通常は基本テンプレートを通じて追加されます)。上記のページの URL が https://xxx.com/common/prefetching.html であると仮定すると、各ページの下部に次のコード行があります:

<iframe src="https://youzan.com/common/prefetching.html" sytle="display:none;"></iframe>  

Verification

特定のファイルがプリフェッチされているかどうかを確認するにはスキームが true 事実上、これは次の手順にすぎません: (ページ A は showcase_d0fbaaef124a8691398704216ccd469a.css を使用しますが、ページ B は使用しないと仮定します)

  1. Chrome ターミナルを開いたときにもキャッシュ機能を有効にしておく
  2. すべてクリアするローカル キャッシュ
  3. ページ B を開き、prefetching.html と添付のリソース ファイルがコンソールにダウンロードされているかどうかを確認します。 / ページ A を開いた後、Ctrl+R を押して更新します。予想どおり、次のような結果が表示されます。これは、これら 2 つの CSS ファイルがキャッシュから読み取られたことを示しています。 Command/Ctrl+R を使用してページを更新すると、次の結果が表示されます。 2 つの違いは、Command/Ctrl+R を使用すると、ブラウザーがキャッシュから静的ファイルを検索することです。このファイルが初めて要求されたときに取得されたキャッシュ制御情報によって、静的ファイルの有効期限が切れているかどうかが決まります。有効期限が切れていない場合は、if-modified-since、Etag、およびその他の情報が使用されます。サーバーからファイルを要求するためのリクエスト ヘッダーとして、ファイルが変更されていないとサーバーが判断した場合、HTTP コード 304 が返され、ブラウザはキャッシュを直接読み取ります。詳細については説明しません。「HTTP キャッシュ」と「HTTP/304 応答について」を参照してください。
  4. 操作手順:

Chrome ターミナルが開いているときでもキャッシュ機能を有効にします: Chrome ターミナルの設定でキャッシュを無効にする (DevTools が開いている間) のチェックを外します

すべてのキャッシュをクリアします: アドレスに chrome と入力しますbar: //settings/clearBrowserData 開いたら、[キャッシュされた画像とファイル] をチェックし、[閲覧データの消去] をクリックします

ブラウザの現在のキャッシュ リソース リストを表示します: chrome://cache/

2 番目のバージョンも、同じ例に従います

現在さあ、上記のファイルプリフェッチソリューションは効果的です。ただし、これは最も粗末な実験版であり、いくつかの問題があります:

prefetching.html 内の js が実行されると、必然的に大量の js エラーが発生します - 不快に見えます ~
  1. iframe を介してプリフェッチをロードします.html は、現在のページの関連リソースの読み込み速度に影響します
  2. prefetching.html は、ページが開かれるたびに読み込まれますが、最初に開いたときに内部の静的ファイルがキャッシュされているため、ダウンロードされません。何度もお願いは不要です。
  3. つまり、オンラインで使用するバージョンは次のとおりです:

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 ファイルは他のタイプのファイルとしてロードされます。最後に、記事「実行せずに CSS/JavaScript をプリロードする」を参照すると、prefetching.html に js ファイルをロードするコードは次のようになります。プリロードされた js ファイルを実行せずにダウンロードするだけ、prefetching.html の読み込みを遅らせる、localstorage レコードの助けを借りて prefetching.html を 1 日 1 回だけロードすることで、バージョン 1 の 3 つの問題は基本的に解決されます。

効果と問題点

サイト全体でモバイルページを立ち上げてから、平均読み込み時間が0.15秒短縮されました。最初の画面時間のデータはありませんが、かなりの収入になるはずです

しかし、このバージョンのリリース後、ページのプリフェッチ中にアニメーションが一時停止することが判明し、最終的にはオブジェクトの読み込みによるものであることが判明しました (この具体的な理由は詳細には調査されていません)。ページは携帯電話でアクセスされ、基本的に Webkit カーネル (Image メソッド) なので、代わりに Image を使用してすべての JS をロードすることにしました。

3 番目のバージョン、完璧です

このバージョンでは、2 番目のバージョンの一時停止アニメーションの問題の解決に加えて、DNS プリフェッチも追加されています。この部分の背景とアイデアについては、私の他の記事「プリロード シリーズ」を参照してください。 1:DNSプリフェッチの正しい利用姿勢》。

<!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 までご連絡ください。