重いサイトの開設を「加速」する

先日、サイトのオープンを加速する必要がありました。 問題は、1つにまとめられ、難読化によって圧縮されたJSファイルのみが500kBを超えるということでしたが、かなり大きなcssもあります。

この点で、ファイルがキャッシュされているユーザー(たとえば、新しいユーザーやビルド後にビルドが変更されたユーザー)は、白い画面を見ながら低速のインターネットアクセスで長時間待つ必要がありました。



さらに、サイトで作業する前にファイルをダウンロードする必要があります。 1つの大きなJSファイルは、必要なページ(jsページ、テンプレート、およびデータ)の読み込み、レンダリングなどを行うクライアントエンジンです。

最後に、ファイルをアップロードするミニスクリプトを書くことにしました。

最後に、すべてのファイルのダウンロードの進行状況が表示された別のページを取得しました。 私の意見では、これは白い画面を見つめて何らかの理由で待つよりもましです。



この方法は、IE9( 自然にニュアンスがある)、IE10以上で動作します-すべての主要なブラウザであるChrome、Firefox、Opera、Safariと同様に完全に動作します。



スタイル
.progress-bar { margin: 200px auto; top : -4px; display: none; width : 400px; border: 1px solid gray; -webkit-border-radius: 8px; -moz-border-radius: 8px; border-radius: 8px; } .progress-bar div { height : 16px; width : 0; background: lightgray; -webkit-border-radius: 8px; -moz-border-radius: 8px; border-radius: 8px; } .progress-bar-text { text-align: center; margin-top: 200px; }
      
      









最も単純なレイアウト:

 <body> <div class="progress-bar"> <div id="progressBar"></div> </div> <div id="loadingPanel" class="progress-bar-text"> ...  ... </div> </body>
      
      







なぜなら プロジェクトはまだjQueryを使用するので、スクリプト用に、少し再構築しましたが、接続することにしました(ほとんどの関数を破棄しました)。



ロードする必要があるもののリストは、fileList変数に保存されます。

 var progressWidth = 0, fileList = [ {type : 'style', url : '/css/bundle.css'}, {type : 'script', url : '/js/bundle.js'} ];
      
      







ファイルのダウンロードを開始する関数は、完了すると、渡されたコールバックを呼び出します。

 function loadFiles(callback) { if (loaded) { //     window.console && console.error('Already loaded.'); return; } loaded = true; var len = fileList.length, count = len; var _afterAll = function() { if (--count == 0) { if (typeof callback == 'function') { setTimeout(callback, 10); } } }; for(var i = 0; i < len; i++) { loadFile(fileList[i], len, _afterAll); } };
      
      







ループでは、ファイルを受信する機能を実行します。

この関数は、progressBar自体を更新します。

しかし、ダウンロードの進行状況を取得する方法は? XMLHttpRequestには、ファイルをダウンロードするためのonprogressイベントが長い間ありました( 詳細については、こちらを参照してください )。

しかし、残念ながらIE9はonprogressを呼び出すことができません。そのため、 新しいwindow.XMLHttpRequest()onprogressイベントが含まれているかどうかを確認します。 プラグが表示されない場合は、通知とともに、待機してください。ロードされます。

ダウンロードが完了すると、ファイルの種類に応じて、スタイルを接続します(今回はブラウザーがキャッシュからファイルを取得するため、ダウンロードしたため)、これがJavaScriptの場合は消去します。



 function loadFile(file, len, callback) { var progressBar = $('#progressBar'), loadingPanel = $('#loadingPanel'); file.url += '?' + REVISION; //     ,        $.ajax({ xhr: function () { var xhr = new window.XMLHttpRequest(); if ('onprogress' in xhr) { progressBar.parent().show(); loadingPanel.hide(); var last = 0, max = 100 / len; xhr.addEventListener("progress", function (evt) { if (evt.lengthComputable) { var percentComplete = Math.min((evt.loaded / evt.total) * max, max); if (last < percentComplete) { progressWidth += percentComplete - last; last = percentComplete; progressBar.width(progressWidth + '%'); } } }, false); } return xhr; }, type: 'GET', url: file.url, success: function (data) { if (file.type == 'style') { $('head').append('<link rel="stylesheet" type="text/css" href="' + file.url + '" media="screen" />'); } else if (file.type == 'script') { evalJS(data); } callback(); }, cache : true }); } function evalJS(text) { try { if (window.execScript) { window.execScript(text); } else { eval.call(window, text); } } catch (error) { window.console && console.error(error); } }
      
      







jQueryでは、 cache:trueプロパティをajaxメソッドに渡しました。これにより、ブラウザが既にキャッシュにあるファイルをダウンロードしないようになります。 。



一般に、すべてが単純ですが、判明したように、Operaもスムーズに動作しません(少なくともバージョン12では) evt.loadedevt.totalの数倍になる可能性があります。

他の落とし穴は見つかりませんでした。



デモ

サンプルソース



All Articles