Babel 等で複数の JavaScript ファイル、特に React, Vue.js の様な巨大なライブラリをまとめて一つの JavaScript ファイルにバンドルし、それを HTML ファイル上で読み込むことが多々あります。この読み込み中の時、マウント用の Element を用意してある HTML ファイルが本当にマウント用の Element 以外見た目が何もない場合、ユーザはそれなりの時間真っ白な画面を見ることになります。これを防ぐにはいくつか方法があります(例えばサーバサイドレンダリング)。この記事では簡単なスクリプトと HTML コードでJavaScript ファイル読み込みのプログレスバーを表示する方法を示します。
実装は次です。
<body> <div id="app"> <!-- React等のマウント先要素内部にプログレス用の要素を置くことでローディング完了後の掃除の手間を省けます --> ロード中です<div id='progress-msg'>0%</div> <!-- progress 要素で簡単にプログレスバーを用意できます。 --> <!-- @see https://developer.mozilla.org/ja/docs/Web/HTML/Element/progress --> <progress id="progress" max="100" value="0"></progress> </div> <script> const jsScriptUrl = '読み込み先JavaScript ファイルの URL'; // プログレスを示すための要素の指定を用意 const progressEl = document.querySelector('#progress') const progressMsgEl = document.querySelector('#progress-msg') /** プログレスが変化する度に画面に反映させる関数 */ const updateProgressEvent = function(event){ // event は XMLHttpRequest の progress_event です // @see https://developer.mozilla.org/ja/docs/Web/API/XMLHttpRequest/progress_event // total は 送られてくるコンテンツの長さがわかる時、それが入ります。 // web サーバ内での gzip 化設定などが原因で total = 0 の場合がままあります。 // そういった時、 0 割りで異常動作になるのを防ぎます if(event.total){ // loaded には読み込み済みのコンテンツの長さが入ります。これでどこまで読み込んだかの割合がわかります progressEl.value = (event.loaded / event.total); // 100 かける、と toFixed メソッドで見やすいパーセンテージを表記します progressMsgEl.innerText = `${((event.loaded / event.total) * 100).toFixed(2)}%` } } // JavaScript ファイル読み込みの XHR です // ajax, axios を使わないのは ajax, axios の読み込み待ちの時間がもったいないからです。 // そういった意味では XHR 同様にブラウザ組み込みの fetch が XHR の代役に向いています。 // fetch のストリーム関連が上手く操れれば XHR より良いかもしれません。 // @see https://developer.mozilla.org/ja/docs/Web/API/XMLHttpRequest const request = new XMLHttpRequest(); request.onprogress=updateProgressEvent;// ↑のプログレス表記、更新イベントをセット request.open('GET', jsScriptUrl, true);// リクエストを初期化 request.onreadystatechange = function () { // 状態が 4 == DONE になったならば読み込んだ内容を script タグにセット // @see https://developer.mozilla.org/ja/docs/Web/API/XMLHttpRequest/readyState if (request.readyState == 4) { // script タグとして HTML に追加 const scriptEl = document.createElement('script'); scriptEl.textContent = request.response; document.head.appendChild(scriptEl); // プログレスが動かなかった時の保険 progressEl.value = 100; progressMsgEl.innerText = `100%` // JavaScript 読み込み後の待ち時間の説明 progressEl.remove() progressMsgEl.innerText = `React 構築中` } }; request.send();// リクエストを送信 </script> </body>
こんな感じのちょっとしたスクリプトで次の様に JavaScript ファイル読み込み中のプログレスバーを作れます。また readyState== 4 になった後の処理を工夫して JavaScritp ファイル以外にも応用できます。