将脚本放在底部的两种不同方式 - 有什么区别?

时间:2014-03-31 09:36:01

标签: javascript html asynchronous-javascript

以下两种解决方案有何区别? 特别是,有一个很好的理由支持2超过1.(注意:请假设要加载的脚本的名称是已知的。问题是关于创建最小脚本以在给定的脚本中加载脚本是否有价值情况)

1 - 底部的脚本

<html>
<body>
...
...
<script src='myScript.js'></script>
</body>
</html>

2 - 底部的脚本加载外部脚本

<html>
<body>
...
...
<script>
    // minimal script to load another script
    var script = document.createElement('script');
    script.src = 'myScript.js'
    document.body.appendChild(script);
</script>
</body>
</html>

5 个答案:

答案 0 :(得分:11)

第二个的一个重要特性是它允许浏览器立即完成对页面的解析,而无需等待脚本加载。这是因为第一个示例允许脚本使用document.write来更改<script>标记周围的解析状态,而第二个示例则不会。

现在,我们知道它位于页面底部,因此没有任何重要的内容可以解析,但这仍然是一个重要的区别。直到解析完成后,浏览器才会触发流行的DOMContentLoaded事件。在方法1中,事件在脚本加载并执行后触发。在方法2中,事件在脚本开始加载之前触发。

以下是一些例子。在这些演示中,DOMContentLoaded侦听器将背景颜色更改为黄色。我们尝试加载一个需要3秒钟才能加载的脚本。

  1. http://jsfiddle.net/35ccs/
  2. http://jsfiddle.net/VtwUV/
  3. (编辑:也许jsfiddle并不是举办这些演示的最佳场所。在缓慢加载脚本加载之前,它不会显示结果。请务必在加载后再次单击“运行”,以查看会发生什么。)

    选择最适合您应用的方法。如果您知道需要在DOMContentLoaded之前运行脚本,请使用方法1.否则,方法2在大多数情况下都非常好。

答案 1 :(得分:5)

<强> 1。底部的脚本

当您使用“同步”脚本标记时,它将阻止浏览器呈现页面,直到加载并执行脚本为止。该方法具有以下效果:

  • 无论您放置脚本标记的位置如何,在下载并执行脚本之前,浏览器都无法触发DOMContentLoaded

  • 在底部放置此类脚本标记只能确保浏览器在被脚本阻止之前呈现所有内容。

<强> 2。底部的脚本加载外部脚本

使用JavaScript注入脚本标记时,它将创建一个不会阻止浏览器的“异步”脚本标记。该方法具有以下效果:

  • 无论您在何处放置生成脚本标记的JavaScript代码,浏览器都会在可用时立即执行它而不会阻止该页面。 DOMContentLoaded应该触发它;无论脚本是否已下载/执行。

第二种方法具有以下优点:

  • 注入脚本标记的脚本可以放在任何位置,包括文档头。
  • 脚本不会阻止渲染。
  • DOMContentLoaded事件不会等待脚本。

第二种方法有以下缺点:

  • 您不能在此类脚本中使用document.write。如果这样做,此类声明可能会擦除文档。
  • 异步执行并不意味着浏览器已完成对页面的解析。保持脚本在可用时立即执行子句。
  • 无法保证执行顺序。示例:如果使用注入的脚本标记加载“library.js”和“use-library.js”,则可以在“library.js”之前加载并执行“use-library.js”。

说了这么多,还有另一种加载脚本的方法,有三种变体:

<script src="myScript.js" async></script>
<script src="myScript.js" defer></script>
<script src="myScript.js" async defer></script>

关于Steve Souders的工作:他为loading scripts without blocking提出了6种技巧。 HTML5中引入的asyncdefer属性涵盖脚本DOM元素脚本延迟技术,他们的浏览器支持对您来说已经足够了担心其他技术。

答案 2 :(得分:3)

这两种初始化脚本的方法基本相同,但如果可以直接输入结果,则没有理由使用第二种方式。但是,您可以将第二个示例包装在$(document).ready()方法中,例如这会导致延迟加载效果。这基本上意味着页面将首先加载,并且在页面加载完成后,它将加载脚本。或者当然,您可以创建一种以这种方式初始化某个脚本的方法。当你有一个仅在某些情况下使用的大脚本时,它很有用。除非您需要,否则这将阻止加载它,从而减少整体加载时间。

答案 3 :(得分:2)

这不是您问题的直接答案,但无论如何都很有用。

第二种方法有时用作库后备 例如,您从Google CDN加载jQuery。但是,如果它因任何原因失败,请从您自己的本地副本加载jQuery。

以下是流行的HTML5 Boilerplate如何推荐这样做:

    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
    <script>window.jQuery || document.write('<script src="js/vendor/jquery-1.11.0.min.js"><\/script>')</script>

答案 4 :(得分:1)

第一种方法意味着脚本标记是硬编码的。第二种方法使用JavaScript动态地将脚本标记添加到页面底部。第二种方法的好处是,如果需要,您可以添加其他逻辑来修改脚本标记。也许您可能希望根据文化,浏览器或您可以在JavaScript中确定的其他因素加载不同的脚本文件。第二种方法还可以加载JavaScript文件,而不会阻止加载其余网页。在方法一中,页面将在到达脚本标记时停止加载,加载JavaScript文件,然后完成加载页面的其余部分。由于此标记位于页面底部,因此不会产生太大差异。

如果您使用JavaScript创建Windows应用商店应用,则建议使用第一种方法,因为这将允许应用程序对JavaScript文件进行字节码缓存,这将使其加载速度更快。