我想知道在性能和易于维护方面,何时应该包含外部脚本或将它们与 html 代码内联编写。
这方面的一般做法是什么?
真实世界场景 - 我有几个需要客户端表单验证的 html 页面。为此,我使用了一个包含在所有这些页面上的 jQuery 插件。但问题是,我是否:
- 编写内联配置此脚本的代码位?
- 在一个文件中包含所有这些 html 页面共享的所有位?
- 将每个位包含在单独的外部文件中,每个 html 页面一个?
谢谢。
我想知道在性能和易于维护方面,何时应该包含外部脚本或将它们与 html 代码内联编写。
这方面的一般做法是什么?
真实世界场景 - 我有几个需要客户端表单验证的 html 页面。为此,我使用了一个包含在所有这些页面上的 jQuery 插件。但问题是,我是否:
谢谢。
在最初发布此答案时(2008 年),规则很简单:所有脚本都应该是外部的。无论是维护还是性能。
(为什么是性能?因为如果代码是分开的,它可以更容易被浏览器缓存。)
JavaScript 不属于 HTML 代码,如果它包含特殊字符(例如<
, >
),它甚至会产生问题。
如今,Web 的可扩展性已经发生了变化。由于发出多个 HTTP 请求的延迟,减少请求的数量已成为一个有效的考虑因素。这使得答案更加复杂:在大多数情况下,仍然建议使用外部 JavaScript。但是对于某些情况,尤其是非常小的代码段,将它们内联到站点的 HTML 中是有意义的。
可维护性绝对是将它们保持在外部的一个原因,但是如果配置是单行的(或者通常比将这些文件外部化所获得的 HTTP 开销短),那么将它们保持内联在性能方面会更好。永远记住,每个 HTTP 请求都会在执行时间和流量方面产生一些开销。
自然,当您的代码超过几行并且并非真正特定于单个页面时,这一切都变得无关紧要。在您希望能够重用该代码的那一刻,将其设为外部。如果你不这样做,看看它的大小然后再决定。
如果你只关心性能,那么这个线程中的大多数建议都是完全错误的,并且在 SPA 时代变得越来越错误,我们可以假设没有 JS 代码的页面是无用的。我花了无数时间优化 SPA 页面加载时间,并使用不同的浏览器验证这些结果。通过重新编排您的 html,全面提高性能可能非常显着。
为了获得最佳性能,您必须将页面视为两级火箭。这两个阶段大致对应于<head>
和<body>
阶段,但可以将它们视为<static>
和<dynamic>
。静态部分基本上是一个字符串常量,您可以尽可能快地将其推下响应管道。如果您使用大量设置 cookie 的中间件(这些需要在发送 http 内容之前设置),这可能会有点棘手,但原则上它只是刷新响应缓冲区,希望在跳转到一些模板代码(razor、php、等)在服务器上。这听起来可能很困难,但我只是解释错了,因为它几乎是微不足道的。您可能已经猜到了,这个静态部分应该包含所有内联和缩小的 javascript。它看起来像
<!DOCTYPE html>
<html>
<head>
<script>/*...inlined jquery, angular, your code*/</script>
<style>/* ditto css */</style>
</head>
<body>
<!-- inline all your templates, if applicable -->
<script type='template-mime' id='1'></script>
<script type='template-mime' id='2'></script>
<script type='template-mime' id='3'></script>
由于将这部分发送到网络上几乎不需要任何费用,因此您可以预期客户端将在连接到您的服务器后大约 5 毫秒 + 延迟时间开始接收此内容。假设服务器相当接近,这个延迟可能在 20 毫秒到 60 毫秒之间。浏览器将在收到此部分后立即开始处理,并且处理时间通常会超过传输时间 20 倍或更多,这现在是服务器端处理该<dynamic>
部分的摊销窗口。
浏览器(chrome,rest 可能慢 20%)处理内联 jquery + signalr + angular + ng animate + ng touch + ng routes + lodash 大约需要 50 毫秒。这本身就非常了不起。大多数 Web 应用程序的代码比所有这些流行的库加起来的代码少,但假设你的代码量差不多,所以我们将在客户端赢得延迟 + 100 毫秒的处理(这种延迟胜利来自第二个传输块)。当第二个块到达时,我们已经处理了所有的 js 代码和模板,我们可以开始执行 dom 转换。
您可能会反对此方法与内联概念正交,但事实并非如此。如果您不是内联,而是链接到 cdns 或您自己的服务器,浏览器将不得不打开另一个连接并延迟执行。由于此执行基本上是免费的(因为服务器端正在与数据库通信),所以必须清楚所有这些跳转的成本都比不执行跳转要高。如果有一个浏览器怪癖说外部 js 执行得更快,我们可以衡量哪个因素占主导地位。我的测量表明,额外的请求会在这个阶段扼杀性能。
我在 SPA 应用程序的优化方面做了很多工作。人们通常认为数据量很重要,而实际上延迟和执行往往占主导地位。我列出的压缩库加起来有 300kb 的数据,压缩后的数据只有 68kb,或者在 2mbit 3g/4g 手机上下载 200ms,这正是在同一部手机上检查是否有相同数据所需的延迟已经在其缓存中,即使它被代理缓存,因为移动延迟税(电话到塔延迟)仍然适用。同时,具有较低首跳延迟的桌面连接通常具有较高的带宽。
简而言之,现在(2014 年),最好内联所有脚本、样式和模板。
编辑(2016 年 5 月)
随着 JS 应用程序的不断增长,我的一些有效负载现在堆叠了 3 多兆字节的缩小代码,很明显,至少应该不再内联常见的库。
外部化 javascript 是雅虎性能规则之一:http: //developer.yahoo.com/performance/rules.html#external
虽然您应该始终将脚本外部化的硬性规则通常是一个不错的选择,但在某些情况下,您可能希望内联一些脚本和样式。但是,您应该只内联您知道会提高性能的东西(因为您已经对此进行了测量)。
我认为特定于一页的短脚本案例(仅)是内联脚本的可辩护案例
应该始终使用外部脚本的另一个原因是为了更轻松地过渡到内容安全策略 (CSP)。CSP 默认禁止所有内联脚本,使您的站点更能抵抗 XSS 攻击。
我会看一下所需的代码,并根据需要将其分成多个单独的文件。每个 js 文件将只包含一个“逻辑集”功能等。例如。所有登录相关功能的一个文件。
然后在每个 html 页面上的站点开发过程中,您只包含需要的那些。当您上线您的网站时,您可以通过将页面所需的每个 js 文件合并到一个文件中来进行优化。
我可以为内联 javascipt 提供的唯一防御是,当使用带有 .net MVC 的强类型视图时,您可以参考我发现有用的 c# variables mid javascript。
三个考虑:
关于将 JavaScript 保持在外部的观点:
ASP.NET 3.5SP1 最近引入了创建复合脚本资源的功能(将一堆 js 文件合并为一个)。这样做的另一个好处是,当 Webserver 压缩打开时,下载一个稍大的文件将比许多较小的文件具有更好的压缩率(也更少的 http 开销、往返等......)。我想这可以节省初始页面加载,然后如上所述启动浏览器缓存。
除了 ASP.NET,这个截屏视频更详细地解释了好处: http ://www.asp.net/learn/3.5-SP1/video-296.aspx
使用 Firebug 也更容易调试外部脚本。我喜欢对我的 JavaScript 进行单元测试并获得所有外部帮助。我讨厌在 PHP 代码和 HTML 中看到 JavaScript,这对我来说是一团糟。
外部脚本的另一个隐藏的好处是您可以通过像jslint这样的语法检查器轻松运行它们。这可以使您免于许多令人心碎、难以发现的 IE6 错误。
在您的场景中,听起来像在页面之间共享的一个文件中编写外部内容对您有好处。我同意上面所说的一切。
在早期原型设计期间,为了快速迭代,保持代码内联,但确保在生产时将其全部外部化。
我什至敢说,如果你不能将所有的 Javascript 放在外部,那么你的设计就很糟糕,你应该重构你的数据和脚本
谷歌已经在它的页面排名测量中包含了加载时间,如果你内联很多,蜘蛛爬过你的页面需要更长的时间,如果你必须包含很多,这可能会影响你的页面排名。无论如何,不同的策略可能会影响您的排名。
好吧,我认为在制作单页网站时应该使用内联,因为脚本不需要跨多个页面共享
拥有内部 JS 专业人员:更容易管理和调试你可以看到正在发生的事情
内部 JS 的缺点:人们可以随意改变它,这真的会惹恼你。
外部 JS 专业人士:不改变你可以看起来更专业(或者至少我是这么认为的)
外部 JS 缺点:更难管理,很难知道发生了什么。
始终尝试使用外部 Js,因为内联 js 总是难以维护。
此外,由于大多数开发人员建议在外部使用 js,因此专业要求您使用外部 js。
我自己使用外部js。