這裡介紹實務上延遲載入各種 JavaScript 的作法,包含 facebook、Google+ 與 twitter 等各類工具。

在網頁中我們可以使用 asyncdefer 的方式來引入外部的 JavaScript 檔案,這樣可以減輕外部 JavaScript 檔對 HTML 解析的效能影響,而這裡我們要介紹另一種在實務上延遲載入各種 JavaScript 程式碼的作法,包含常見的社群按鈕以及各種 JavaScript 工具,例如 facebook、Google+ 與 twitter 等。

延遲載入 JavaScripts

若單純只是使用 defer 來引入 JavaScript 檔案的話,瀏覽器會在背景載入該 JavaScript 檔,然後在 HTML 解析完成後執行,雖然不會打斷 HTML 的解析,但是多少還是會佔用網路連線與頻寬,影響其他網頁元素的載入速度。

有另外一種作法是將這個 JavaScript 程式碼的內容貼在 </body> 之前,但是這樣做也是會有同樣的問題,它會在完整的網頁載入完成之前就先執行 JavaScript 的內容。

如果要讓 defer.js 這個 JavaScript 檔案盡可能延後載入,可以將下面這段 JavaScript 放置在 </body> 之前:

<script type="text/javascript">
function downloadJSAtOnload() {
  var element = document.createElement("script");
  element.src = "defer.js";
  document.body.appendChild(element);
}
if (window.addEventListener)
  window.addEventListener("load", downloadJSAtOnload, false);
else if (window.attachEvent)
  window.attachEvent("onload", downloadJSAtOnload);
else
  window.onload = downloadJSAtOnload;
</script>

這樣的作法是在整個完整的網頁(包含網頁的圖片、CSS 與 JavaScript 檔)都載入完成之後,才使用 JavaScript 插入 defer.js 這個 JavaScript 檔,所以對整個網頁內容的影響是最小的。

我們可以利用這樣的作法,將許多不同來源的 JavaScript 程式全部放在一個 defer.js 中,這樣不僅可以讓程式碼更精簡,也可以減少連線數。

Facebook 按鈕

facebook 按鈕預設的 JavaScript 程式碼分為兩部份,第一個部份是 facebook 的 JavaScript SDK,官方建議放在 <body> 之後,而第二部份則是外掛程式顯示位置的 HTML 碼:

<!-- Facebook JavaScript SDK,放置在 body 中 -->
<div id="fb-root"></div>
<script>(function(d, s, id) {
  var js, fjs = d.getElementsByTagName(s)[0];
  if (d.getElementById(id)) return;
  js = d.createElement(s); js.id = id;
  js.src = "//connect.facebook.net/zh_TW/sdk.js#xfbml=1&version=v2.6&appId=241371325930982";
  fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));</script>

<!-- 將此程式碼放置在你希望外掛程式顯示的頁面位置 -->
<div class="fb-like" data-href="http://blog.gtwang.org/" data-layout="standard" data-action="like" data-show-faces="true" data-share="true"></div>

facebook 這種方式是讓瀏覽器在解析 HTML 時就直接載入並執行他的程式碼,這樣會直接影響網頁載入的速度,若要改善這個問題可以將這裡 <script> 裡面的 JavaScript 程式碼搬到剛剛我們上面介紹的 defer.js 中,而其餘的純 HTML 碼則維持不變,這樣就可以強制 facebook 的外掛程式在網頁完全載入之後才執行。

Twitter 按鈕

twitter 按鈕的程式碼分為兩部份,第一行是 HTML 碼,而第二行則是 JavaScript 碼:

<a href="https://twitter.com/share" class="twitter-share-button">Tweet</a>
<script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?'http':'https';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+'://platform.twitter.com/widgets.js';fjs.parentNode.insertBefore(js,fjs);}}(document, 'script', 'twitter-wjs');</script>

twitter 這種載入方式也是會影響 HTML 解析的,我們可以將這裡第二行的 JavaScript 程式碼移到上面介紹的 defer.js 中,而第一行的 HTML 碼則維持不變,這樣就可以改善網頁載入的問題。

Google Plus 按鈕

Google Plus 所提供的程式碼本身就已經有使用 defer 的方式載入了,如果將它的 JavaScript 程式碼放在 </body> 之前的話,對網頁載入的影響就會比較小。

<!-- 將這個標記放在標頭中,或放在內文結尾標記前面。 -->
<script src="https://apis.google.com/js/platform.js" async defer>
  {lang: 'zh-TW'}
</script>

<!-- 在您要顯示「+1 按鈕」的位置放上這個標記。 -->
<div class="g-plusone" data-annotation="inline" data-width="300"></div>

如果要讓 Google Plus 的 JavaScript 程式碼完全不影響網頁的載入,可以修改上面的 downloadJSAtOnload 函數,仿照 defer.js 的載入方式,插入 Google Plus 用的 JavaScript 程式碼:

<script type="text/javascript">
function downloadJSAtOnload() {
  var element = document.createElement("script");
  element.src = "defer.js";
  document.body.appendChild(element);

  // 加入 Google Plus 用的 JavaScript
  var googlePlusJS = document.createElement("script");
  googlePlusJS.src = "https://apis.google.com/js/platform.js";
  googlePlusJS.innerHTML = "{lang: 'zh-TW'}";
  document.body.appendChild(googlePlusJS);
}
if (window.addEventListener)
  window.addEventListener("load", downloadJSAtOnload, false);
else if (window.attachEvent)
  window.attachEvent("onload", downloadJSAtOnload);
else
  window.onload = downloadJSAtOnload;
</script>

這樣一來 Google Plus 的 JavaScrit 對於網頁的效能影響又會降低一些。

以上我們介紹這些延遲載入 JavaScript 的方式,其實適用於各種 JavaScript 外掛程式,原則上就是只要碰到 inline 的 JavaScript 就直接放進 defer.js 中,從外部引入的 JavaScript 檔就仿照 defer.js 的方式載入。

參考資料:varvy.com