将JS文件放在网页底部是否实际上是一个好的做法?

7
广泛建议将JS文件放在页面底部,以便先加载HTML代码。这样,在等待页面完全加载时,访问者仍可看到某些内容。然而,我认为这有以下劣势:
  1. 现代设计主要依赖于JS,在加载JS之前,页面会显得丑陋。
  2. 如果在加载过程中断开连接(根本不加载JS),则访问者将错失一些网站功能(可能非常重要);而且他们不会意识到这是加载问题(需要重新加载页面)。
  3. 如果服务器端脚本(例如PHP)在页脚之前在脚本的最后一个位置遇到错误导致退出,访问者将无法使用整个页面功能(通过JS);但是如果在顶部加载JS,则只会错过页脚或半个页面。
  4. 如果先加载JS,浏览器将同时加载其他内容(如图像);但是如果最后加载JS,则可能会增加加载时间。因为JS文件很大(例如JQuery和JQuery UI),所有小东西(如图像)都已加载完毕,我们正在加载一个大文件,排在最后一个。
更新:5. 由于必须在代码之前加载jQuery库,如果在页脚(例如footer.php)中加载jQuery库,则无法为不同页面(在body内部)添加自定义jquery代码。
请纠正我是否有误!将JS文件放在页脚中仍然有益吗?

1
是的 - 这里有一篇关于#1的好文章http://paulirish.com/2009/avoiding-the-fouc-v3/...如果您的设计在JavaScript加载之前被破坏,那么您需要为该用例进行设计。 - aknosis
您的第一点是错误的,因为它很可能会成为可访问性的障碍。除非交互专门针对演示文稿的专用变化,否则演示文稿应始终发生在JavaScript之外。 - austincheney
7个回答

4
在头部的脚本标签会阻止所有其他请求。如果您有像这样的10个标签:

<script src="http://images.apple.com/home/scripts/promotracker.js"></script>

...它们将顺序执行。没有其他文件会同时被下载。因此,它们会增加页面加载时间。

在这里查看HeadJS作为一个解决方案示例。


@Ali 你可以将它放在 </body> 前面,因为它仍然会阻止 <body> 后面的内容。或者简单地使用 <body onLoad='...'>(或 jQuery 的替代方案),而适用于多脚本页面的最优雅的方法是 HeadJS。($Michael +1 for HeadJS) - Arman P.

4

编辑:针对我在这个话题上看到的人们的棉花,我要补充另一点。

附加点#5。如果你真正关心JS-fail上的处理行为,我的意思是,人们在浏览时关闭JS,那么你应该拥抱渐进增强的概念。例如,你可以设计一个手风琴菜单,通过默认的悬停来作为弹出式菜单,是的,只使用CSS,然后通过更改关键类别在JS启用时删除该行为。这样,如果用户关闭JS,则可以访问链接,但在JS工作时,他们会获得增强的行为。

但你不应该尝试处理应该有JS文件的页面上整个JS文件的缺失,因为页面在后端被破坏了。处理意外情况是一回事,但在生产中不应该考虑完成HTML文件构建之前就提供错误场景,特别是如果你的模板语言中有实际的后端代码(你不应该有),等待泄漏并给想成为黑客的人提供可能感兴趣的东西。损坏的页面应该作为错误消息提供。

================================

  1. 完全错误。任何时候你使用JS来调整页面的初始静态外观,你都是在做错事。保持关注点的分离,你的页面将更加灵活。使用JS来调整页面的静态样式不是现代的,它是反向的,你可以告诉jQuery移动的家伙我这么说。如果你绝对必须支持IE6、IE7和IE8,请告诉客户,如果他们拒绝接受任何替代方案来为他们的5%客户群体提供绝对优美的降级,那么这将花费他们多少钱。

  2. 如果你的页面在没有JS之前需要很长时间才能加载,那么你还有其他问题需要解决。你加载了多少资源?你的PHP在进行什么神秘的预处理?我称之为后端或设计骗局。

  3. 你是说只有半个页面有可用的JS比完全不可接受好一些吗?无论他们是谁,都不要放开这个客户。

  4. 当最小化时,jQuery的大小大约与中等大小的JPEG相当。

注意:在页面顶部具有一些JS并不完全不可接受。一些专业代码,如分析工具或画布规范化器需要它。但任何不需要的东西都应该在底部。每次解析JS时,整个页面加载和流程计算过程都会停顿。将JS推到底部可以提高感知的页面加载时间,并应该提供证据,表明你团队中有人需要迅速采取措施来弄清楚他们的代码为什么失败或如何处理他们刚刚缩小而不是重新格式化的25兆字节png-24。


非常信息丰富的答案!但我不同意,有时我们需要通过JS来设计,比如手风琴菜单,因为隐藏/显示应该通过点击实时在JS上完成。如果不加载JS,所有菜单都将被展开。 - Googlebot
@Ali - 请将您的菜单默认折叠,并可从顶部条目导航。这样虽然会让用户需要更多点击,但是网站的工作效果将更好。 - RobG
是的,但如果JS被关闭或文件加载失败,那就行不通了。这不是一个简单的问题,我认为除了重新设计之外,没有正确的答案。 - Andy Davies
你不应该设计处理文件加载失败的意图。那是一个有缺陷的应用程序,完全不能接受。计划处理频繁更换的图像错误是可以接受的,但JS和CSS文件则完全荒谬。 - Erik Reppen

2
您需要考虑“在执行一些javascript之前,我是否需要DOM准备好”。基本上,您可以将脚本标记放在页面底部,以确保DOM已准备就绪。如果您在头部链接样式并正确地设置页面样式,则不应该出现“丑陋”的情况。其次,如果您依赖于某些部分的javascript显示来处理DOM对象,则我建议使用更多的ajax调用来避免此问题。最好的两个世界。页面加载了您所需的内容,然后ajax调用正在获取HTML以填充页面的其他部分。

并非总是可以仅使用CSS进行设计。例如,在手风琴菜单中,我们需要通过JS隐藏关闭的菜单项,因为隐藏/显示是通过点击实时完成的。 - Googlebot
JS 通过设置 CSS 隐藏 HTML 元素。您可以在 CSS 中将默认状态设置为关闭,然后让 JS 处理它或使用渐进增强技术。 - Erik Reppen

2
将JS放在页面底部或异步加载是受推荐的原因是JS会减缓页面加载速度。如果一些浏览器下载JS会阻塞其他并行下载,在所有浏览器中执行JS会阻塞UI线程,从而影响渲染(在某些情况下还会阻塞解析)。将它放在底部或异步加载尝试将问题推迟到对访问者页面加载体验影响更小的时候。不要忘记,无论你的页面多么漂亮,如果加载时间太长,人们就不会等待,2/3秒左右开始出现问题。
  • 现代设计可能比以往更少地依赖JS——是的,我们仍然需要polyfill,但随着浏览器变得更好,我们可以通过CSS做更多事情。
  • 这可能对于像Backbone.js应用程序这样的东西来说是真的,但是如果缺乏JS会破坏网站,那么我认为设计应该是不同的。
  • 如果服务器端脚本死掉了,可能还有其他问题需要担心,而且不能保证页面有足够的内容是有用的。
  • 不!JS会阻塞UI线程,在某些情况下会阻塞下载,所以图片也会延迟。另外,由于JS正在使用连接,因此可用于并行下载的连接较少。
  • 看看@samsaffron关于延迟加载jQuery的文章-http://samsaffron.com/archive/2012/02/17/stop-paying-your-jquery-tax
  • 如果你可以延迟JS加载,那么就应该这样做。

    1

    每个人的需求都不同,让我们来看看你的列表:

    1)我从来没有因为javascript而遇到页面布局或样式的问题。如果你的HTML和CSS有序,那么缺少javascript几乎是不可见的。 您可以在css中隐藏元素,并在它们准备好时使用javascript显示它们。您可以使用 jQuery的.show();方法

    这里是一个例子:

    <!DOCTYPE html>
    <html>
    <head>
      <style>
      div { background:#def3ca; margin:3px; width:80px;
      display:none; float:left; text-align:center; }
      </style>
      <script src="http://code.jquery.com/jquery-latest.js"></script>
    </head>
    <body>
      <button id="showr">Show</button><button id="hidr">Hide</button>
      <div>Hello 3,</div><div>how</div><div>are</div><div>you?</div>
    <script>
    $("#showr").click(function () {
      $("div").first().show("fast", function showNext() {
        $(this).next("div").show("fast", showNext);
      });
    });
    $("#hidr").click(function () {
      $("div").hide(1000);
    });
    </script>
    </body>
    </html>
    

    如果您仍然遇到问题,您可以将JavaScript拆分为您的网站依赖项和其他脚本,并将其中一些放在页眉中,另一些放在页脚中。

    2)这是用户错误,您无法控制它,但您可以检查所需功能是否存在并尝试重新加载它。大多数插件都会提供一些确认,以确定它们是否正在运行,因此您可以运行测试并尝试重新加载它们。

    您还可以延迟加载文件,直到用户需要它们,例如等待他们聚焦到form上以加载验证脚本,或滚动到某个特定点以加载屏幕下方的内容的代码。

    3)如果页面die,那么你最终会得到一个半空白的页面。使用PHP 5,您可以使用exceptions进行更好的错误处理。

     

    if (!$result = mysql_query('SELECT foo FROM bar', $db)) {
            throw new Exception('You fail: ' . mysql_error($db));
    }
    

    和这个

    try
    {
      // Code that might throw an exception
      throw new Exception('Invalid URL.');
    }
    catch (FirstExceptionClass $exception) 
    {
      // Code that handles this exception
    } 
    catch (SecondExceptionClass $exception) 
    {
      // you get the idea what i mean ;)
    }
    

    4) 如果你压缩你的脚本,它们不应该比图片大多少。JQuery经过压缩和gzip处理后只有32KB。JQuery-UI的脚本是51KB。这还不错,大多数插件应该比这更小。

    所以我建议你应该尽力达到你想要的结果,但要寻找减少错误和冗余代码的最佳实践。总有更好的方法来解决问题...


    1

    我对将脚本放在页脚并不是很熟悉,但你可能需要了解一下各种方法来告诉页面在完全加载后才运行JavaScript。

    这打开了几个选项 - 你可以让JS在页面准备好后动态加载外部脚本。

    你也可以隐藏部分或全部页面内容,然后在页面准备好后再显示它。只需确保用JS隐藏它,这样非JS浏览器仍然可以看到它。

    请参考以下内容:


    当然我使用 $(document).ready(function() {;但是我指的是加载像jQuery这样的JavaScript库。应该什么时候加载它?在头部还是底部? - Googlebot
    如果您正在使用document.ready jQuery函数,则必须将jQuery库链接到标头中,否则在浏览器尚未加载它们时尝试执行jQuery函数可能会导致时间不匹配。 - DavidB
    @DavidBeaton 谢谢,这就是我遇到的问题。 - Googlebot

    1

    我偶尔会建议将Javascript放在页面底部(就在</body>之前),但只有在新手程序员无法处理window.onload<body onload...>的情况下,这是他们代码最容易适应并使其正常工作的最简单的调整方式。

    我同意你提到的实际缺点,需要权衡迈克尔关于加载时间影响的注意事项。在大多数情况下,将脚本加载在页面的<head>中胜出。


    我更喜欢使用 $(document).ready(function() {;,因为 window.onload 可能会使未完全加载的页面非常丑陋。如果设计依赖于 JS。 - Googlebot
    那种方法如何帮助延迟JS的加载? - Andy Davies

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接