我什么时候应该使用内联 vs. 内联外部 JavaScript?
-
02-07-2019 - |
题
我想知道什么时候应该包含外部脚本或将它们与 html 代码内联编写,就性能和易于维护而言。
这方面的一般做法是什么?
真实场景 - 我有几个需要客户端表单验证的 html 页面。为此,我使用了一个包含在所有这些页面上的 jQuery 插件。但问题是,我是否:
- 编写内联配置此脚本的代码位?
- 将所有位包含在一个文件中,并在所有这些 html 页面之间共享?
- 将每一位包含在一个单独的外部文件中,每个 html 页面一个?
谢谢。
解决方案
在这个答案最初发布时(2008 年),规则很简单:所有脚本都应该是外部的。既用于维护又用于性能。
(为什么要表现?因为如果代码是独立的,则浏览器可以更轻松地对其进行缓存。)
JavaScript 不属于 HTML 代码,并且如果它包含特殊字符(例如 <
, >
)它甚至会产生问题。
如今,网络可扩展性已经发生了变化。由于发出多个 HTTP 请求的延迟,减少请求数量已成为一个有效的考虑因素。这使得答案变得更加复杂:在大多数情况下,外部使用 JavaScript 是 仍然 受到推崇的。但对于某些情况,尤其是非常小的代码片段,将它们内联到网站的 HTML 中是有意义的。
其他提示
可维护性无疑是将它们保持在外部的一个原因,但如果配置是单行的(或者通常比将这些文件设为外部的 HTTP 开销短),那么从性能角度来说,将它们保持为内联会更好。永远记住,每个 HTTP 请求都会在执行时间和流量方面产生一些开销。
当然,当您的代码长于几行并且并非真正特定于单个页面时,这一切都变得无关紧要。当您希望能够重用该代码时,请将其设为外部代码。如果不这样做,请查看其大小然后再决定。
外部化 javascript 是 yahoo 性能规则之一:http://developer.yahoo.com/performance/rules.html#external
虽然您应该始终外部化脚本的硬性规则通常是一个不错的选择,但在某些情况下您可能希望内联某些脚本和样式。但是,您应该只内联您知道会提高性能的内容(因为您已经对此进行了测量)。
如果你只关心性能,那么这个线程中的大多数建议都是完全错误的,并且在 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,其余的可能慢20%)需要大约50ms来处理内联jquery + signalr + Angular + ng animate + ng touch + ng paths + lodash。这本身就非常令人惊奇。大多数 Web 应用程序的代码少于所有这些流行库的代码总和,但假设您拥有同样多的代码,因此我们将在客户端上赢得延迟 + 100 毫秒的处理(此延迟胜利来自第二个传输块)。当第二个块到达时,我们已经处理了所有 js 代码和模板,并且可以开始执行 dom 转换。
您可能会反对该方法与内联概念正交,但事实并非如此。如果您不是内联,而是链接到 cdns 或您自己的服务器,浏览器将不得不打开另一个连接并延迟执行。由于此执行基本上是免费的(因为服务器端正在与数据库通信),因此必须清楚的是,所有这些跳转都会比根本不进行跳转花费更多。如果浏览器有一个怪癖,说外部 js 执行得更快,我们就可以衡量哪个因素占主导地位。我的测量表明,额外的请求会破坏此阶段的性能。
我在 SPA 应用程序的优化方面做了很多工作。人们通常认为数据量很重要,但实际上延迟和执行往往占主导地位。我列出的缩小库总共有 300kb 的数据,而压缩后的数据仅为 68 kb,或者在 2mbit 3g/4g 手机上下载 200 毫秒,这正是在同一部手机上检查是否具有相同数据所需的延迟即使它是代理缓存,也已经在其缓存中,因为移动延迟税(电话到塔延迟)仍然适用。同时,具有较低第一跳延迟的桌面连接通常具有较高的带宽。
简而言之,现在(2014 年),最好内联所有脚本、样式和模板。
编辑(2016 年 5 月)
随着 JS 应用程序的不断增长,我的一些有效负载现在堆叠了高达 3+ MB 的精简代码,很明显,至少不应再内联公共库。
我觉得 特定于一页,简短的脚本案例 是(唯一)内联脚本的合理情况
您应该始终使用外部脚本的另一个原因是为了更轻松地过渡到 内容安全策略 (CSP). 。CSP 默认禁止所有内联脚本,使您的网站更能抵抗 XSS 攻击。
我会查看所需的代码,然后根据需要将其分成多个单独的文件。每个 js 文件只包含一组“逻辑”函数等。例如。所有登录相关功能的一个文件。
然后,在每个 html 页面上的网站开发过程中,您只包含需要的内容。当您上线网站时,您可以通过将页面所需的每个 js 文件合并到一个文件中来进行优化。
我可以为内联 javascipt 提供的唯一防御是,当在 .net MVC 中使用强类型视图时,您可以参考我发现有用的 c# 变量和 javascript。
三个考虑:
- 您需要多少代码(有时库是一流的消费者)?
- 特异性:该代码仅在该特定文档或元素的上下文中起作用吗?
- 文档中的每个代码往往会使其变得更长,从而变慢。除了 SEO 考虑因素之外,您还可以最小化内部脚本......
使用 Firebug 还可以更轻松地调试外部脚本。我喜欢对我的 JavaScript 进行单元测试并获得所有外部帮助。我讨厌在 PHP 代码和 HTML 中看到 JavaScript,这对我来说看起来是一团糟。
关于将 JavaScript 保持在外部:
ASP.NET 3.5SP1 最近引入了创建复合脚本资源的功能(将一堆 js 文件合并为一个)。这样做的另一个好处是,当打开 Web 服务器压缩时,下载一个稍大的文件将比许多较小的文件具有更好的压缩率(也更少的 http 开销、往返等...)。我想这可以节省初始页面加载,然后浏览器缓存就会启动,如上所述。
除了 ASP.NET,此截屏视频更详细地解释了其优点:http://www.asp.net/learn/3.5-SP1/video-296.aspx
外部脚本的另一个隐藏好处是您可以通过语法检查器轻松运行它们,例如 jslint. 。这可以让您避免许多令人心碎、难以发现的 IE6 错误。
在您的场景中,听起来将外部内容写入在页面之间共享的一个文件中对您来说是有好处的。我同意上面所说的一切。
在早期原型设计过程中,保持代码内联,以利于快速迭代,但确保在投入生产时将其全部外部化。
我什至敢说,如果你不能将所有的 Javascript 都放在外部,那么你的设计就很糟糕,你应该重构你的数据和脚本
谷歌已将加载时间纳入其页面排名测量中,如果您内联很多,蜘蛛将花费更长的时间爬行您的页面,如果您必须包含太多,这可能会影响您的页面排名。无论如何,不同的策略可能会影响您的排名。
好吧,我认为在制作单页网站时应该使用内联,因为脚本不需要在多个页面之间共享
始终尝试使用外部 Js,因为内联 js 总是难以维护。
此外,专业上要求您使用外部 js,因为大多数开发人员建议使用外部 js。
我自己使用外部js。