2016-11-29 60 views
2

我使用這個腳本如果我推遲JS文件加載,以改善pagespeed我如何調用加載函數?

<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> 

其中defer.js是整個網站的我所有的JS功能我精縮合並後的文件。

這種技術是爲了推遲,以防止惱人的谷歌的PageSpeed警告負載:

「消除阻止呈現的JavaScript和CSS在上面屏內容」

但現在,我所有的電話document.ready > function A現在搞砸了......

有沒有修復它?

+0

巧妙使用腳本加載事件 –

+0

您必須多給我們一點。你得到什麼錯誤?您是否嘗試加載單個文件?你已經完成了什麼類型的調試? –

+1

爲什麼不把腳本標籤放在頁尾,在關閉標籤之前?這應該消除警告並提高性能。 – Paul

回答

-2

把你的javascript代碼放在頁面的最底部怎麼樣?這樣它就不會阻塞任何渲染過程。

由於ready甚至已經被調用,因此代碼將不會被執行,所以您應該將所有代碼包含在匿名函數中,以便立即執行。

(function(){ 
//do stuff here 
})(); 
+0

'所以你應該包裝所有的代碼在匿名函數,所以它會立即執行' - 這是沒有道理的,在執行代碼時,將代碼封裝在IIFE中並不會改變 –

+0

抱歉,但是您的意思是「執行時沒有更改」?可能是我誤解了這個問題。正如我所看到的,他的問題是在doc準備好之後加載的代碼未被執行,因爲它等待已經調用的doc準備好的事件,所以他應該很好地在加載到瀏覽器,對吧? – Oksid

+0

你說你應該把所有的代碼包裝在一個IIFE中,以便立即執行......當代碼運行時,在IIFE中包裝代碼不會改變,如果代碼立即在IIFE內部運行,相同的代碼立即在IIFE之外運行 - I不能使這個陳述更簡單 - 我根本不是在談論這個問題,只是關於一個IIFE如何改變代碼執行的錯誤陳述 - 它不是 –

0

好吧,

所以我不能說這是最好的做法,但它似乎很合法的:

如果您還沒有與網絡工作者出場,我強烈建議至少瀏覽一下API。

<head> 
    <script 
     src="https://code.jquery.com/jquery-2.2.4.min.js" 
     integrity="sha256-BbhdlvQf/xTY9gja0Dq3HiwQF8LaCRTXxZKRutelT44=" 
     crossorigin="anonymous"> 
    </script> 
    <title>Time for Web Workers!</title> 
</head> 
<body id="body"> 
    <script type="text/javascript"> 
     var worker = new Worker("js.js"); 
     worker.addEventListener("message", 
      function (evt) { 
      var script = document.createElement("script"); 
      script.innerHTML = evt.data; 
      document.getElementById('body').appendChild(script); 
      },false); 
     worker.postMessage(1);  
    </script> 

網絡工作者符使用JavaScript時,單線程的限制。工人們遇到的巨大挫折是他們無法訪問dom。他們可以做的大部分是通過消息計算和傳遞數據。

啊,但消息!

這是它有點混亂,但堅持與我。

var worker = new Worker("js.js"); 
// any data can be used as arg, but needed to trigger 'messages' listener 
worker.postMessage(1); 

我第一次嘗試發送postMessage()功能使用本地js文件創建一個新的Worker。這有效,但它會導致jQuery保持undefined,因爲該腳本不適用於該線程。單獨的線程,單獨的資源> _ <

爲了解決這個問題,我們需要Worker將代碼發回主線程以在dom的jQuery腳本下執行。我們可以通過設置我們的本地js文件來偵聽消息事件,並將其作爲字符串返回到代碼庫

這可以通過使用虛擬導入您的精縮的本地文件,並解析爲一個字符串,或者通過簡單地創建從你的精縮腳本的字符串,並使用它,像這樣做:

addEventListener("message", 
    function (evt) { 
     var script = 
      "$(document).ready(
      function() { 
       var thisThing = 'blah';alert(thisThing); 
      })"; 
      postMessage(script); 
      }, false); 

回到了主線程,我們設置一個事件監聽器來偵聽消息。在這個函數中,我們需要創建一個新的<script>元素並在最終將其附加到body之前插入字符串化的代碼庫。

worker.addEventListener("message", 
    function (evt) { 
     var script = document.createElement("script"); 
     script.innerHTML = evt.data; 
     document.getElementById('body').appendChild(script); 
    },false); 

注意

  1. 我還沒有大的腳本
  2. 我只用一個本地開發服務器來測試這個
  3. 測試這個我沒有測試任何$(document).ready() - 重型代碼在本地腳本,所以我不知道這是否會解決您的問題..
  4. 我很開心這樣做:P