2016-11-29 63 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