【问题标题】:Should I split my javascript into multiple files?我应该将我的 javascript 拆分为多个文件吗?
【发布时间】:2013-03-02 03:22:55
【问题描述】:

我习惯于使用 Java,其中(我们知道)每个对象都定义在自己的文件中(一般来说)。我喜欢这个。我认为它使代码更易于使用和管理。

我开始使用 javascript,我发现自己想要为我在单个页面上使用的不同脚本使用单独的文件。我目前将自己限制在几个 .js 文件中,因为我担心如果我使用的更多,我将来会因为我目前无法预见的事情而感到不便。也许是循环引用?

简而言之,将我的脚本分成多个文件是不好的做法吗?

【问题讨论】:

  • 由于下载时间的原因,您应该始终尝试使您的脚本成为一个单一的大文件。但是,如果您使用压缩器(您应该),它们可以为您将多个源文件合并为一个。因此,您可以继续处理多个文件,然后将它们压缩为单个文件以进行分发。
  • @Dave,您绝对应该将其发布为答案!
  • @Dave:如果这是一个答案,我会赞成。 :D
  • 如果您关心 OO,那么无论您使用哪种语言,每个文件一个类(模块)都是一个好主意。您所要做的就是将所有文件压缩成一个
  • @Dave 因为浏览器可以并行下载文件(仍然按顺序执行),所以五个 1MB 文件的下载速度将比单个 5MB 文件快。见stackoverflow.com/questions/4877321/…

标签: javascript html


【解决方案1】:

这里有很多正确答案,具体取决于您的应用程序的大小以及您将其交付给谁(我的意思是预期的设备等),以及您可以在服务器端完成多少工作以确保您针对的是正确的设备(对于大多数非企业凡人来说,这距离 100% 可行还有很长的路要走)。

在构建您的应用程序时,“类”可以愉快地驻留在自己的文件中。
在跨文件拆分应用程序时,或在处理具有过多假设的构造函数的类时(例如实例化其他类),循环引用或死端引用是一个大问题。
有多种模式可以解决这个问题,但最好的模式当然是让您的应用程序考虑到 DI/IoC,这样就不会发生循环引用。
您还可以查看 require.js 或其他依赖加载程序。您需要获得的复杂程度取决于您的应用程序有多大,以及您希望所有内容有多私密。

在为您的应用程序提供服务时,提供 JS 的基线是连接您需要的所有脚本(以正确的顺序,如果您要实例化假设其他内容存在的内容),并将它们作为一个文件提供页面底部。

但这是基线。
其他方法可能包括“延迟/延迟”加载。
加载您需要的所有内容,以使页面提前运行。
同时,如果您的小程序或小部件在页面加载时不需要 100% 的功能,事实上,它们需要用户交互,或者在执行任何操作之前需要延迟,然后为这些加载脚本小部件延迟事件。在用户在选项卡上点击 mousedown 的位置加载选项卡式小部件的脚本。现在您只加载了您需要的脚本,并且仅在需要时加载,没有人会真正注意到下载的微小延迟。

将此与试图将 40,000 行应用程序填充到一个文件中的人进行比较。
只有一个 HTTP 请求,只有一个下载,但解析/编译时间现在变成了明显的几分之一秒。

当然,延迟加载并不是将每个类留在自己的文件中的借口。
那时,您应该将它们打包成模块,并提供将运行整个小部件/小程序/任何东西的文件(除非有其他逻辑位置,直到以后才需要功能,并且它隐藏在进一步的交互之后)。

您还可以将这些模块的加载放在计时器上。
预先加载基线应用程序内容(同样在页面底部,在一个文件中),然后设置半秒左右的超时时间,然后加载其他 JS 文件。
您现在不会妨碍页面的操作或用户移动的能力。这当然是最重要的部分。

【讨论】:

  • 这就是我要说的。你昨天不是为C++ 人写了一个关于延迟/承诺对象的长答案吗?
  • 我做到了。对于没有简单答案的问题,我喜欢长篇大论。
  • 写得很好。我也wax pedantic in double-time at times。有趣的东西。
  • 好吧,糟了。感谢您的信任投票,尽管事实上我的句子开始与下一个工作日的开始呈线性相关关系融为一体,而且我对我的写作进行批评的意愿与所花费的时间和所写的行数成反比。此外,这是关于伪元素占位符放置的一篇特别迂腐的文章。
【解决方案2】:

从 2020 年开始更新:按照互联网标准,这个答案已经很老了,而且与今天的全貌相去甚远,但仍然偶尔会看到投票,所以我觉得有必要提供一些关于自发布以来发生的变化的提示。多年来对async 脚本加载的良好支持、HTTP/2 的服务器推送功能以及对加载过程的一般浏览器优化都对将 Javascript 分解为多个文件对加载性能的影响产生了影响。

对于刚开始使用 Javascript 的人,我的建议保持不变(使用捆绑器 / 缩小器并相信它会默认做正确的事情),但对于任何有更多经验的人发现这个问题,我会邀请他们研究 async 加载和服务器推送带来的新功能。

2013 年的原始答案:


由于下载时间的原因,您应该始终尝试使您的脚本成为一个单一的大文件。但是,如果您使用压缩器(您应该),它们可以为您将多个源文件合并为一个。因此,您可以继续处理多个文件,然后将它们压缩为单个文件以进行分发。

主要的例外是公共库,例如 jQuery,您应该始终从公共 CDN 加载它们(用户很可能已经加载了它们,因此不需要再次加载它们)。如果您确实使用公共 CDN,总是如果失败,则可以从您自己的服务器加载。

正如 cmets 中所指出的,真实的故事要复杂一些;

脚本可以同步 (<script src="blah"></script>) 或异步 (s=document.createElement('script');s.async=true;...) 加载。同步脚本会阻止加载其他资源,直到它们被加载。比如:

<script src="a.js"></script>
<script src="b.js"></script>

将请求 a.js,等待它加载,然后加载 b.js。在这种情况下,将 a.js 与 b.js 结合起来,一举加载它们显然会更好。

同样,如果a.js有加载b.js的代码,不管是不是异步的,你都会遇到同样的情况。

但是如果你同时加载它们异步,并且取决于客户端与服务器的连接状态,以及一大堆只能通过分析才能真正确定的考虑因素,它可以更快。

(function(d){
    var s=d.getElementsByTagName('script')[0],f=d.createElement('script');
    f.type='text/javascript';
    f.async=true;
    f.src='a.js';
    s.parentNode.insertBefore(f,s);
    f=d.createElement('script');
    f.type='text/javascript';
    f.async=true;
    f.src='b.js';
    s.parentNode.insertBefore(f,s);
})(document)

它要复杂得多,但会同时加载 a.js 和 b.js 而不会相互阻塞或其他任何东西。最终,async 属性将被正确支持,您将能够像同步加载一样轻松地做到这一点。最终。

【讨论】:

  • 下载时间是否严格?我的理解是,担心的是浏览器将处理的同时 http 请求的数量 - 略有不同(也许我很迂腐?) - 但我听说它对脚本没有相同的限制因为页面中有常规内容/资产,因此可以减轻任何实际问题,尽管我找不到任何参考。
  • combine assets 的方法,但如果我们谈论性能,请将其留在HTML 文件中。这本身就是最快的,对吧?不过,我怀疑这是否适用于所有情况。
  • @JaredFarrish Javascript 不应出现在 HTML 中,因为它通常在同一站点的页面之间共享,并且您只希望用户下载一次。还有使者:两者都发挥作用。它确实有更长的下载时间,仅仅是因为它需要进行更多的往返,但同时连接也可能是一个问题。除非您异步加载脚本,否则浏览器将阻止加载任何内容(包括其他脚本),直到下载完成,因此在一般情况下,它们会一个接一个地加载。
  • 规则是用来打破的。在想象我所说的内容时不要那么僵化,并试着看出这不是一个规则,这是一个最佳实践和一个有效的考虑,所有人都应该思考和决定做什么。
  • @JaredFarrish 也许我更新的答案更适合您的观点。我试图涵盖所有情况。
【解决方案3】:

这里有两个问题:a) 易于开发 b) 下载 JS 资产时的客户端性能

就开发而言,模块化从来都不是坏事;还有一些 Javascript 自动加载框架(如 requireJSAMD)可用于帮助您管理模块及其依赖项。

但是,为了解决第二点,最好将所有 Javascript 合并到一个文件中并缩小它,这样客户端就不会花费太多时间下载所有资源。有一些工具 (requireJS) 也可以让您执行此操作(即将所有依赖项组合到一个文件中)。

【讨论】:

    【解决方案4】:

    这取决于您现在使用的协议。如果您使用http2,建议您拆分js文件。如果你使用http,我建议你使用缩小的js文件。

    这里是使用httphttp2的网站示例

    谢谢,希望对你有帮助。

    【讨论】:

    • “虽然此链接可能会回答问题,但最好在此处包含答案的基本部分并提供链接以供参考。如果链接页面发生更改,仅链接的答案可能会失效。
    【解决方案5】:

    这并不重要。如果您在多个文件中使用相同的 JavaScript,那么最好有一个包含 JavaScript 的文件可以从中获取。所以你只需要从一个地方更新脚本。

    【讨论】:

    • 您是否建议为所有 JavaScript 使用一个 JS 文件?这很重要。
    • 如果你查看 jQuery 的库,它的代码很多。许多人选择使用整个包而不是分解所需的代码。因此,如果您没有流量很大的一方,我会说使用一个文件。否则,最好在代码中组织更好的结构。但主要是我想你是否想在不同的文件中使用相同的功能。 :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多