我想知道何时应该包括外部脚本或将它们与html代码内联地编写,以提高性能并简化维护。
一般做法是什么?
真实场景-我有几个需要客户端表单验证的html页面。为此,我使用了所有这些页面中都包含的jQuery插件。但是问题是,我是否:
- 编写代码位以内联方式配置此脚本?
- 在所有这些html页面之间共享的一个文件中包含所有位?
- 将每个位都包含在一个单独的外部文件中,每个html页面一个?
谢谢。
我想知道何时应该包括外部脚本或将它们与html代码内联地编写,以提高性能并简化维护。
一般做法是什么?
真实场景-我有几个需要客户端表单验证的html页面。为此,我使用了所有这些页面中都包含的jQuery插件。但是问题是,我是否:
谢谢。
Answers:
在最初发布此答案(2008年)时,规则很简单:所有脚本都应在外部。兼顾维护和性能。
(为什么要执行性能?因为如果代码是分开的,则浏览器可以更轻松地缓存它。)
JavaScript不属于HTML代码,并且如果包含特殊字符(例如<
,>
),它甚至会产生问题。
如今,Web可伸缩性已经改变。由于发出多个HTTP请求的延迟,减少请求的数量已成为一个有效的考虑因素。这使答案变得更加复杂:在大多数情况下,仍然建议使用JavaScript外部。但是对于某些情况,尤其是很小的代码段,将它们内联到网站的HTML中是有意义的。
可维护性绝对是将它们保持在外部的原因,但是,如果配置是单行的(或者通常比将这些文件外部生成的HTTP开销要短),则将它们保持为内联在性能方面会更好。永远记住,每个HTTP请求都会在执行时间和流量方面产生一些开销。
自然,当您的代码比几行长并且实际上并不是特定于单个页面时,所有这些都变得无关紧要。当您希望能够重用该代码时,请将其设置为外部。如果不这样做,请查看其大小并决定。
javascript的外部化是yahoo性能规则之一:http : //developer.yahoo.com/performance/rules.html#external
虽然始终应始终将脚本外部化的严格原则是一个不错的选择,但在某些情况下,您可能希望内联某些脚本和样式。但是,您应该仅内联一些您知道的内容,这些内容会提高性能(因为您已经对此进行了测量)。
如果只关心性能,则该线程中的大多数建议都是错误的,并且在SPA时代正变得越来越错误,在SPA时代,我们可以假设没有JS代码的页面是无用的。我花了无数小时来优化SPA页面的加载时间,并使用不同的浏览器来验证这些结果。总体而言,通过重新编排html可以显着提高性能。
为了获得最佳性能,您必须将页面视为两级火箭。这两个阶段大致对应于<head>
和<body>
阶段,但可以将它们视为<static>
和<dynamic>
。静态部分基本上是一个字符串常量,您可以尽可能快地将其推入响应管道。如果您使用许多设置cookie的中间件(需要在发送http内容之前进行设置),这可能会有些棘手,但是原则上,它只是刷新响应缓冲区,希望在跳入一些模板代码(剃刀,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>
由于通过有线发送该部分几乎不需要花任何费用,因此可以预期客户端在连接到服务器后将在大约5ms +延迟的时间开始接收该部分。假设服务器合理关闭,则此延迟可能在20毫秒至60毫秒之间。浏览器在获得此部分后将立即开始对其进行处理,通常,处理时间将占传输时间的20倍或更多,这是您在服务器端处理该部分的摊销窗口。<dynamic>
部分。
浏览器需要大约50毫秒(chrome,其余时间可能慢20%)来处理内联jquery + signalr + angular + ng animate + ng touch + ng route + lodash。就其本身而言,这是非常惊人的。大多数Web应用程序的代码都少于所有流行的库的代码总和,但是假设您拥有的代码也是如此,因此我们将赢得客户端上的延迟+100毫秒的处理时间(此延迟来自第二个传输块)。到第二个块到达时,我们已经处理了所有js代码和模板,并且可以开始执行dom转换。
您可能会反对这种方法与内联概念正交,但事实并非如此。如果您不是内联,而是链接到CDN或您自己的服务器,则浏览器将不得不打开另一个连接并延迟执行。由于此执行基本上是免费的(因为服务器端正在与数据库进行通信),因此必须清楚,所有这些跳转将比根本不执行跳转花费更多。如果有一个浏览器怪癖说外部js执行得更快,我们可以衡量哪个因素占主导。我的评估表明,在此阶段,额外的请求会降低性能。
我在优化SPA应用程序方面做了很多工作。人们通常认为数据量很大,而实际上延迟和执行通常是主要的。我列出的缩小的库最多可添加300kb的数据,而压缩后仅为68kb,在2mbit 3g / 4g手机上的下载时间为200ms,这恰好是同一部手机检查是否具有相同数据所需要的延迟。即使已缓存代理,也已在其缓存中添加了缓存,因为移动延迟税(电话到塔延迟)仍然适用。同时,具有较低第一跳延迟的台式机连接通常无论如何具有较高的带宽。
简而言之,现在(2014年),最好内联所有脚本,样式和模板。
编辑(2016年5月)
随着JS应用程序的不断增长,并且我的某些有效载荷现在可以堆叠3兆字节以上的精简代码,显然,至少在普通库中不再应该内联。
我认为特定于一页的短脚本案例是(仅)内联脚本的合理案例
您应该始终使用外部脚本的另一个原因是为了更轻松地过渡到内容安全策略(CSP)。CSP默认情况下禁止所有内联脚本,从而使您的站点更能抵抗XSS攻击。
在保持JavaScript外部性方面:
ASP.NET 3.5SP1最近引入了创建复合脚本资源的功能(将一堆js文件合并为一个)。这样做的另一个好处是,当打开Web服务器压缩时,下载一个稍大的文件将具有比许多小文件更好的压缩率(还减少了HTTP开销,往返等)。我想这可以节省初始页面加载,然后如上所述启动浏览器缓存。
除了ASP.NET,此截屏视频更详细地说明了好处:http : //www.asp.net/learn/3.5-SP1/video-296.aspx