【问题标题】:Why inline JavaScript is bad?为什么内联 JavaScript 不好?
【发布时间】:2013-09-30 21:55:27
【问题描述】:

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

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

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');
};

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

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

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

当然,这不仅限于函数,因为我们在整个网站上都有很多 addEventListeners,它们会在每个不需要它们的页面上触发。

【问题讨论】:

  • 您可以拥有多个具有所有功能的外部 JS 文件,然后是每个页面的特定文件。这将包含通常是内联 JS 的内容
  • 没有人说过你的整个网站的每一个功能都需要在一个 Javascript 文件中......为什么你的外部 JS 文件中的代码量与你的“内联”Javascript?
  • @RoryPicko92 一个文件中所有JS代码的一个主要优点是它会被缓存,而不需要通过浏览加载。
  • 最重要的是:请检查最近在浏览器中建立“内容安全策略”的尝试......这将使外部 JS 成为强制性

标签: javascript performance dom-events unobtrusive-javascript


【解决方案1】:

不建议内联静态资源(在你的情况下是内联 javascript),因为你不能缓存它们

缓存静态资源可减少回访者的页面加载大小,从而提高页面加载速度。然而,这是以额外的 HTTP 请求 which should be avoided 为代价的。

只要静态资源与 HTTP 请求相比,额外的大小可以忽略不计,那么实际上建议保持该资源内联。

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

所以,作为对您的标题的回应 – 内联 javascript 本身还不错。是否值得通过 HTTP 请求缓存资源是一种平衡。

【讨论】:

  • 虽然还有许多其他有效的问题,但这是问题的正确答案,也是迄今为止选择内联还是外联时影响最大的问题。
  • 这是一个非常好的答案。我刚刚和某人讨论过这个问题,我认为这是关于平衡的。有很多博客说内联不好,但我不同意他们的推理。我使用了很多只能在一个页面上运行的内联 sn-ps。更通用、更可重用的 sn-ps 被放入每个页面都包含的单个 js 文件中。
  • 在这种情况下,外部文件可以并行下载,并通过边缘缓存(如 cloudfront)提供服务。因此,没有内联对性能的影响可以忽略不计,因为它很混乱,所以它很少是一个好主意。
  • 为什么它不能缓存整个文档,包括内联资源?您是在谈论缓存以供重用吗?
  • 这是否意味着如果我将所有 js 代码放入一个函数并放入一个单独的文件中并仅内联调用此函数,那么将只缓存该函数名称并且它可以独立于函数大小?或者如果函数定义很大就不好?
【解决方案2】:
  • 避免内联 js 不是基于性能...而是更多关于可维护性以及将表示层 (html) 与控制器层 (js) 分开。

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

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

  • 保持您的 html 干净,并且您知道在发生任何 js 错误时到哪里查看而不是多个模板。

【讨论】:

  • 您可以在构建过程中嵌入 JS,就像将多个 JS 文件合并为一个进行部署一样
【解决方案3】:

你应该阅读不显眼的 javascript, http://en.wikipedia.org/wiki/Unobtrusive_JavaScript.

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

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

【讨论】:

    【解决方案4】:

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

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

    (我敢打赌,即使您有 26 个函数在寻找具有不同类名的元素,但对于性能,总是首先测量。)

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

    值得记住在页面加载时必须发生的所有事情:

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

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

    但是,我再说一遍,因为这是最重要的一点,这一切都会因您的代码而异。如果你想保持良好的表现,你的第一步和最后一步必须是衡量它。

    【讨论】:

    • getElementsByClassName 是一个惰性枚举...(或者他们称之为“实时”),仅仅调用它不是任何工作。
    【解决方案5】:

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

    对于内联:

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

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

    现在还有其他的理论

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

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

    【讨论】:

      【解决方案6】:

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

      【讨论】:

      • “感觉”是什么意思?您能否对您的答案进行一些解释,以便其他人可以从中学习?
      【解决方案7】:

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

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

      因此,如果您的内联脚本小于 1 KB - 没关系,否则 - 避免使用。

      这里是来源:The cost of JavaScript in 2019

      【讨论】:

        【解决方案8】:

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

        【讨论】:

        • 虽然取决于 JavaScript,不是吗。例如,在我运行的站点中,我在正文标记之后使用此脚本:&lt;script&gt;(function (body_el){body_el.className=body_el.className.replace('no-js','js');})(document.getElementsByTagName('body')[0]);&lt;/script&gt;。它是 141 字节,这是在 gzip 压缩之前。不是特别重,我认为这是在 body 上更改类的最快方法,因为在渲染 body 标签后不会触发任何 JavaScript 事件。
        • 另外:“其中包括要求页面,这将帮助我们将 js 代码用于每个功能” - 我不知道这是什么意思。
        • 如果我们需要使用 ajax 进行大 js 计算,那么我们需要,否则我们可以在页面上添加 js 的小功能。
        【解决方案9】:

        内联样式/脚本与 html 内容混淆,难以区分。在 Web 开发中拥有可维护代码的关键之一是编写非编写者易于阅读的代码。将脚本标签混合到您的 html 中会使您很难找到影响其余代码的函数。将 Javascript 放在 .js 文件中,将 Styles 放在 CSS 文件中,让代码更清晰易读。

        【讨论】:

        • 使用当前的 JS 技术,例如将所有内容连接到一个大型 JS 应用程序文件中,也不是那么容易发现问题。主要问题是关于性能,而不是可维护性
        猜你喜欢
        • 2011-02-06
        • 1970-01-01
        • 1970-01-01
        • 2012-08-08
        • 1970-01-01
        • 1970-01-01
        • 2016-12-28
        • 2013-09-08
        • 1970-01-01
        相关资源
        最近更新 更多