什么时候应该使用内联与外部Javascript?


129

我想知道何时应该包括外部脚本或将它们与html代码内联地编写,以提高性能并简化维护。

一般做法是什么?

真实场景-我有几个需要客户端表单验证的html页面。为此,我使用了所有这些页面中都包含的jQuery插件。但是问题是,我是否:

  • 编写代码位以内联方式配置此脚本?
  • 在所有这些html页面之间共享的一个文件中包含所有位?
  • 将每个位都包含在一个单独的外部文件中,每个html页面一个?

谢谢。

Answers:


114

在最初发布此答案(2008年)时,规则很简单:所有脚本都应在外部。兼顾维护和性能。

(为什么要执行性能?因为如果代码是分开的,则浏览器可以更轻松地缓存它。)

JavaScript不属于HTML代码,并且如果包含特殊字符(例如<>),它甚至会产生问题。

如今,Web可伸缩性已经改变。由于发出多个HTTP请求的延迟,减少请求的数量已成为一个有效的考虑因素。这使答案变得更加复杂:在大多数情况下,仍然建议使用JavaScript外部。但是对于某些情况,尤其是很小的代码段,将它们内联到网站的HTML中是有意义的。


6
@尼克:大多数问题都可以克服。不过最好不要首先生成它们。
康拉德·鲁道夫

17
内联时,有时您会获得更好的性能。查看google.com的来源。他们知道自己在做什么。
callum 2012年

13
@callum Google与99.999999%的网站有不同的用例。当然,它们的测量非常仔细,即使最小的差异也很重要。但是仅仅因为他们发现在特定的用例中,内联会更好地工作(可能是因为脚本经常更改吗?)并不意味着我们可以从中得出通用规则,甚至不应该忽略“常规”规则。规则(外部化脚本)。
Konrad Rudolph

8
@KonradRudolph-同意,不应从Google的方法中得出任何一般性规则。我只是说这暗示着可能值得质疑您的答案中的规则。无论如何,我认为Google这样做的原因是为了减少HTTP请求,这可能会使超过0.000001%的网站受益。带宽越来越高,但往返时间保持不变。有时,删除整个串行HTTP请求要比外部JS的缓存优势好。当然取决于您的JS的大小。
callum 2012年

5
@callum尽管确实如此,但有关缓存的观点仍然很重要。仅当访问者不返回(然后您将获得的页面点击量不足以使其变得重要)或内容更改频繁而导致缓存脚本文件无济于事时,减少往返次数才是重要的。
康拉德·鲁道夫2012年

31

可维护性绝对是将它们保持在外部的原因,但是,如果配置是单行的(或者通常比将这些文件外部生成的HTTP开销要短),则将它们保持为内联在性能方面会更好。永远记住,每个HTTP请求都会在执行时间和流量方面产生一些开销。

自然,当您的代码比几行长并且实际上并不是特定于单个页面时,所有这些都变得无关紧要。当您希望能够重用该代码时,请将其设置为外部。如果不这样做,请查看其大小并决定。


5
这是我的关注之一。对几行代码单独使用HTTP请求似乎很浪费。
Dan Burzo

您能否为代码发布示例配置?如果IMO字符数少于300个且绝对是特定于页面的,则将其内联。
Horst Gutmann

这应该是imo的最佳答案
sgarcia.dev,2016年

@Dan请记住,单独的请求仅在第一次发生。如果您希望用户加载页面不止一次,则高速缓存的外部(即使是几行)显然比等待n = 2 +页面加载时的那几行字节更快。
jinglesthula

@HorstGutmann如何使文件具有外部可维护性?我个人更愿意使用外部js,但是是否有一些目标使其易于维护?
jinglesthula

21

javascript的外部化是yahoo性能规则之一:http : //developer.yahoo.com/performance/rules.html#external

虽然始终应始终将脚本外部化的严格原则是一个不错的选择,但在某些情况下,您可能希望内联某些脚本和样式。但是,您应该仅内联一些您知道的内容,这些内容会提高性能(因为您已经对此进行了测量)。


1
我认为雅虎还建议将所有的JavaScript到一个HTTP调用过-这并不意味着脚本都应该在同一个文件虽然发展过程中
保罗·香农

同样,如上所述,HTTP / 2也改变了“ 1呼叫”的做法。
jinglesthula

19

如果只关心性能,则该线程中的大多数建议都是错误的,并且在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兆字节以上的精简代码,显然,至少在普通库中不再应该内联。


我没有得到它,现在是您在服务器端处理<dynamic>部分的摊销窗口 -服务器处理所需的内容,然后才提供整个呈现的html(head + body),以及其他服务器处理的内容之后需要吗?
BornToCode 2015年

@BornToCode的想法是让客户端在服务器端要做的同时做点事情。因为需要对客户端库进行解释-最好在服务器上进行任何计算之前启动该过程。摊销窗口是客户端处理JS所花费的时间。如果您安排2级火箭,则可以免费获得该窗口。
Gleno


9

实际上,使用内联javascript有一个很好的案例。如果js足够小(单行),由于两个因素,我倾向于使用javascript内联:

  • 地方性。无需浏览外部文件即可验证某些javascript的行为
  • AJAX。如果要通过AJAX刷新页面的某些部分,则可能会丢失该部分的所有DOM处理程序(onclick等),具体取决于绑定它们的方式。例如,使用jQuery可以使用livedelegate方法来规避此问题,但是我发现,如果js足够小,则最好将其内联。

5

您应该始终使用外部脚本的另一个原因是为了更轻松地过渡到内容安全策略(CSP)。CSP默认情况下禁止所有内联脚本,从而使您的站点更能抵抗XSS攻击。


4

我将看一看所需的代码,并将其分为所需的多个独立文件。每个js文件只能包含一个“逻辑集”的函数等。所有登录相关功能的一个文件。

然后,在每个html页面上的网站开发过程中,您只需包含所需的页面。当您上线站点时,可以通过将页面需要的每个js文件合并为一个文件来进行优化。


4

我可以为内联javascipt提供的唯一防御措施是,当在.net MVC中使用强类型视图时,您可以在javascript中引用c#变量,我发现它很有用。


3

三个注意事项:

  • 您需要多少代码(有时库是一流的使用者)?
  • 特殊性:此代码仅在此特定文档或元素的上下文中起作用吗?
  • 文档中的每个代码都会使它变长,从而变慢。除了SEO考虑因素之外,您还可以将内部脚本最小化...

2

使用Firebug调试外部脚本也更容易。我喜欢对JavaScript进行单元测试,并获得所有外部帮助。我讨厌看到PHP代码和HTML中的JavaScript对我来说似乎很混乱。


2

在保持JavaScript外部性方面:

ASP.NET 3.5SP1最近引入了创建复合脚本资源的功能(将一堆js文件合并为一个)。这样做的另一个好处是,当打开Web服务器压缩时,下载一个稍大的文件将具有比许多小文件更好的压缩率(还减少了HTTP开销,往返等)。我想这可以节省初始页面加载,然后如上所述启动浏览器缓存。

除了ASP.NET,此截屏视频更详细地说明了好处:http : //www.asp.net/learn/3.5-SP1/video-296.aspx


2

外部脚本的另一个隐藏优势是,您可以轻松地通过语法检查器运行它们,例如 jslint之。这样可以避免您遇到许多令人困扰的,难以发现的IE6错误。


1

在您的方案中,听起来好像将外部内容写到页面之间共享的一个文件中对您来说是件好事。我同意上述所有内容。


1

在早期原型制作期间,为了快速迭代而使代码保持内联,但是请确保在生产时将其全部置于外部。

我什至敢于说,如果您不能将所有Javascript放在外部,那么您手中的设计很糟糕,应该重构数据和脚本


1

Google已将载入时间纳入其网页排名度量中,如果您内联很多,蜘蛛将需要更长的时间爬过您的网页,这可能会影响您的网页排名。无论如何,不​​同的策略都可能影响您的排名。


1

好吧,我认为在制作单页网站时应该使用内联,因为脚本无需在多个页面之间共享


-3

总是尝试使用外部Js,因为内联js总是很难维护。

此外,由于大多数开发人员建议在外部使用js,因此专业上要求您使用外部js。

我自己使用外部js。


2
专业要求?为什么?谁说的?
锡耶
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.