为什么内联 JavaScript 不好?

Why inline JavaScript is bad?

提问人:Googlebot 提问时间:9/25/2013 最后编辑:Brian Tompsett - 汤莱恩Googlebot 更新时间:6/11/2020 访问量:21887

问:

始终建议通过将所有代码放在一个文件中来避免内联 Javascript 代码,该文件包含在所有页面中。我想知道,这是否不会导致繁重页面的性能问题。JS

例如,假设我们有几十个这样的函数

function function1(element){
var el=document.getElementsByClassName(element);
var size=el.length;
if(size==0) return;
for(i=0;i<size;i++){
// the process
}
}

在每个页面上,我们需要运行函数来了解 HTML 中是否有相应的元素。

window.onload = function(){
function1('a');
....
function26('z');
};

但是如果将所有函数保存在外部文件中,并通过内联调用函数,我们只能调用当前页面中需要的函数:JSJavaScript

<script type="text/javascript">
window.onload = function(){
function6('f');
};
</script>

从性能的角度来看,通过内联 Javascript 调用函数(这当然不是最佳实践)以避免调用页面中不需要的大量函数,这难道不是有益的吗?

当然,这不仅限于功能,因为我们为整个网站提供了很多功能,这些功能在每个页面上都会触发,而不需要它们。addEventListener

JavaScript 性能 dom-events unobtrusive-javascript

评论

3赞 rorypicko 9/25/2013
您可以拥有多个具有所有功能的外部 JS 文件,然后是每个页面的特定文件。它将包含通常内联 JS 的内容
0赞 devnull69 9/25/2013
从来没有人说过,你整个网站的每一个功能都需要在一个Javascript文件中......为什么与“内联”Javascript 相比,外部 JS 文件中的代码量会有所不同?
0赞 Googlebot 9/25/2013
@RoryPicko92一个文件中所有 JS 代码的一个主要优点是它将被缓存,并且不需要通过浏览加载。
1赞 devnull69 9/25/2013
最重要的是:请查看最近在浏览器中建立“内容安全策略”的尝试......这将使外部 JS 成为强制性的
1赞 cssyphus 3/19/2015
另请参阅此精彩讨论:programmers.stackexchange.com/questions/86589/...

答:

7赞 gmaliar 9/25/2013 #1

http://en.wikipedia.org/wiki/Unobtrusive_JavaScript,您应该阅读有关不显眼的 javascript 的信息。

还有其他解决方案可以不为每个网页加载 assets 目录中的所有 javascript 文件,一个名为 requirejs 的解决方案应该签出,http://requirejs.org/ .

此外,作为一般经验法则,您不应该在页面加载时添加所有事件侦听器,那么不存在的 dom 对象呢?它会抛出 javascript 错误,并且会比平时更多地破坏您的代码。

43赞 Nils Kaspersson 9/25/2013 #2

不建议内联静态资源(在本例中为内联 javascript),因为您无法缓存它们

缓存静态资源可以减少回访者的页面加载大小,从而提高页面加载速度。但是,这是以额外的 HTTP 请求为代价的,应该避免这样做

每当静态资源太小,以至于与 HTTP 请求相比,额外的大小可以忽略不计,那么实际上建议将该资源保持在内联状态。

通常,将 javascript 库保留在外部(可缓存)文档中,同时保持少量脚本内联是一个好主意。

所以,为了回应你的标题——内联 javascript 本身还不错。这是一个平衡,是否值得一个HTTP请求来缓存资源。

评论

2赞 Billy Moon 9/26/2013
虽然还有许多其他有效的担忧,但这是问题的正确答案,也是迄今为止在选择内联与外部时影响最大的问题。
0赞 Olav Grønås Gjerde 1/30/2016
这是一个很好的答案。我刚刚和某人讨论过这个问题,我推断这是关于平衡的。有很多博客说内联不好,但我不同意他们的推理。我使用了很多只会在一个页面上运行的内联代码段。更通用、更可重用的片段被放入每个页面都包含的单个 js 文件中。
0赞 max 11/23/2017
对于外部文件,它可以在 paralell 中下载,并通过 cloudfront 等边缘缓存提供。因此,不内联的性能影响足以说它很少是一个好主意,因为它很混乱。
1赞 Константин Ван 8/18/2019
为什么它不能缓存整个文档,包括内联资源?您是在谈论用于重用的缓存吗?
1赞 Asker 6/24/2023
HTML 页面不是缓存的吗?如果是这样,那么我不明白为什么内联 Javascript 也不会被缓存。
19赞 Abhidev 9/25/2013 #3
  • 避免内联 js 不是基于性能的......但它更多的是关于可维护性和将表示层(HTML)与控制器层(JS)分开。

  • 随着项目规模的增加,在不同的页面上使用内联 js 将使您和其他人难以维护。

  • 此外,使用单独的 js 文件可以鼓励可重用性和模块化代码设计。

  • 保持你的HTML干净,当发生任何JS错误而不是多个模板时,你知道在哪里看。

评论

0赞 6/7/2017
您可以将 JS 嵌入到构建过程中,就像将多个 JS 文件合并为一个文件进行部署一样
3赞 Paul D. Waite 9/25/2013 #4

在页面上运行不必要的 JavaScript 可能会导致该页面加载缓慢。这取决于正在运行的 JavaScript。

你可以通过对示例代码进行计时来测试它,并查看 JavaScript 重复运行需要多长时间。getElementsByClassName

(我敢打赌,即使你有 26 个函数在寻找具有不同类名的元素,也不需要很长时间,但对于性能,总是首先进行测量。

如果执行时间是一个问题,您可以编写 JavaScript,使其主要位于一个文件中,但在需要它的页面上公开您从内联 JavaScript 运行的函数,而不是通过 JavaScript 文件中的事件运行它。onload

不过,值得记住的是,加载页面时必须发生的一切:

  1. 浏览器从其缓存中获取页面,或发送 HTTP 请求以查看页面自缓存以来是否已更改,和/或为页面本身发送 HTTP 请求。
  2. 浏览器解析和呈现页面,暂停以获取和运行任何外部 JavaScript,并在解析和呈现的同时获取样式表和图像。
  3. 浏览器运行任何 JavaScript 集,以便在文档就绪时运行。
  4. 浏览器运行任何设置为在页面加载时运行的 JavaScript。

虽然你当然可以编写运行缓慢的 JavaScript,但总体上,将 JavaScript 放在外部文件中,因此放在用户浏览器的缓存中,而不是通过内联来增加页面大小,可能更好。一般来说,网络往往比 JavaScript 解析/执行慢得多。

但是,我再说一遍,因为这是最重要的一点,这将根据您的代码而有所不同。如果你想保持良好的表现,你的第一个也是最后一个行动必须是衡量它。

评论

0赞 Esailija 9/26/2013
getElementsByClassName 是一个惰性枚举...(或他们称之为“生活”)仅仅称呼它不是什么工作。
1赞 Sunil Verma 9/25/2013 #5

在放置 JS 代码时需要牢记各种情况。

对于内联 :

  1. 如果您需要快速更改某些内容,则无需导航到外部文件,因此在本地效果更好

  2. 如果你在页面的某些元素中使用AJAX,你可能会丢失该部分的所有DOM元素onclick等,这显然取决于你如何绑定它们。例如,您可以使用 live 或 delegate,以防您使用 jQuery 来避免上述问题......但是我发现,如果JS足够小,最好只是将其内联。

现在有其他理论

外部化 javascript 是 yahoo 的性能规则之一:

http://developer.yahoo.com/performance/rules.html#external

0赞 Niklesh Jain 9/26/2013 #6

使 js 内联到所有页面会使应用程序变得繁重,因此我们应该使用外部 js,其中包括需要有助于我们将 js 代码用于每个功能的页面。

评论

0赞 Paul D. Waite 9/26/2013
不过取决于 JavaScript,不是吗。例如,在我运行的站点中,我在 body 标记之后内联使用此脚本:。它是 141 个字节,这是在 gzip 之前。不是特别重,我认为这是在 body 上更改类的最快方法,因为在呈现 body 标签后没有任何 JavaScript 事件触发。<script>(function (body_el){body_el.className=body_el.className.replace('no-js','js');})(document.getElementsByTagName('body')[0]);</script>
0赞 Paul D. Waite 9/26/2013
另外:“其中包括需要有助于我们将 js 代码用于每个功能的页面”——我不知道这意味着什么。
0赞 Niklesh Jain 10/17/2013
如果我们需要使用 ajax 进行大的 js 计算,那么我们当然需要否则我们可以在页面上添加 js 的小功能。
0赞 Timothy Trousdale 11/19/2015 #7

内联样式/脚本与 html 内容混淆,并且很难区分。在 Web 开发中拥有可维护代码的关键之一是编写易于被未编写代码的人阅读的代码。将脚本标签混合到 html 中会使你很难找到一个影响其余代码的函数。将 Javascript 放在 .js 文件中,将样式放在 CSS 文件中,使代码更简洁,更具可读性。

评论

0赞 Nico Haase 6/11/2020
使用当前的 JS 技术,例如将所有内容连接到一个大型 JS 应用程序文件中,发现问题也不是那么容易。主要问题是关于性能,而不是关于可维护性
1赞 Malaka Silva 5/26/2020 #8

IMO 这取决于页面。有时对于特定的页面和脚本很小,放入外部文件是没有意义的。

评论

0赞 Nico Haase 6/11/2020
你说的“感觉”是什么意思?你能对你的答案做一些解释,以便其他人可以从中学习吗?
0赞 Mohammed Shareef C 9/18/2023
@NicoHaase可能,不值得付出努力。从外部文件加载一个非常小的脚本不会对性能产生任何影响。
2赞 Ruslan Korkin 6/11/2020 #9

根据 的 “” 演示,其中一项建议是避免使用大型内联脚本Addy OsmaniThe cost of JavaScript#PerfMatters Conference 2019

避免使用大型内联脚本(因为它们仍在 主线程)。一个好的经验法则是:如果脚本超过 1 kB, 避免内联它(也因为 1 kB 是代码缓存启动的时候 外部脚本)。

因此,如果您的内联脚本小于 1 KB,那很好,否则 - 避免它。

这是来源:2019 年 JavaScript 的成本