JavaScript/jQuery 最佳实践: 集中化 vs. 规范化 (Web 应用)

10

想象一下一个 Web 应用程序,它有数十个页面组(pg1、pg2...),其中一些页面组需要特定于它们的 JavaScript 代码,但不适用于整个应用程序。例如,在 window.resize() 上进行一些视觉修复可能仅在 pg2 中相关,而在其他地方则不相关。

以下是一些可能的解决方案:

1/ 集中式:为整个应用程序设置一个脚本文件,处理所有页面组。很容易知道相关 DOM 对象是否存在,因此所有不相关的页面只需增加一个小的额外 if()。最大的优点是所有 JS 仅需加载一次,适用于整个 Web 应用程序,无需修改 HTML 代码。缺点是在不相关的页面上添加了额外的检查。

2/ 混合式:集中式脚本检查页面上特定函数的存在,并在存在时启动它。例如,我们可以添加一个

if (typeof page_specific_resize === 'function') page_specific_resize();

在这种情况下,特定的页面组将具有以下功能:
<script>
function page_specific_resize() {
    //....
}
</script>

优点在于代码仅存在于相关页面,因此不会在每个页面上进行测试。缺点是HTML的额外大小会导致整个页面组的结果。如果有超过几行的代码,则页面组可能能够加载一个特定于其的附加脚本,但这样我们就要在那里添加一个HTTP调用,以可能在集中式脚本中节省一些数据。
哪种做法是最佳实践?请评论这些解决方案或提出您自己的解决方案。添加一些资源来支持您更好的主张(考虑性能和易维护性)将会很好。最详细的答案将被选中。谢谢。

2
我更喜欢你提供的“混合”解决方案,但还有一些事情需要考虑:如果你的几个pg1pg2不需要大量的JavaScript代码,你可能希望将它们集中在一起,以减少JavaScript文件的数量。这样可以使应用程序更轻松调试,因为你不需要浏览多个文件夹来找到与相关页面关联的适当函数。不方便的是,你将加载无用的函数,这意味着pg1的所有函数也会为pg2pg3加载,这可能会降低每个页面的加载速度。 - Anwar
6
这是基于个人观点的,不应该出现在stackoverflow上。 - Arnold Daniels
@Jasny 我认为这些解决方案对社区会有益处。 - jv-k
3个回答

5

由于这是一个假设情景,我们没有数据去计算最繁忙的页面数量、总脚本大小等等,因此很难想出最佳解决方案。

尽管如此,我找不到特定答案,即最佳实践TM,但有一些人们普遍认同的观点。

1)缓存:

根据这个:

https://developer.yahoo.com/performance/rules.html

在现实世界中使用外部文件通常会产生更快的页面,因为浏览器会缓存JavaScript和CSS文件

2) 最小化

根据雅虎链接的说法:

"[最小化] 通过减少下载文件的大小来提高响应时间性能"

3) HTTP请求

最好减少HTTP调用(基于社区答案)。

一个大的javascript文件还是多个较小的文件?

优化javascript加载的最佳实践

4) 您是否真的需要该特定脚本?

根据:https://github.com/stevekwan/best-practices/blob/master/javascript/best-practices.md

“JavaScript 应该用于为您的网站增加额外的功能,而不应该是您的网站运行所必需的。”
这取决于您需要加载的资源。要看特定页面组被加载的频率或您期望它被请求的频率有多高。Web 应用程序是单页吗?每个具体脚本都是做什么的?
如果脚本加载一个表单,用户将不需要再访问该页面。用户以后仍然需要互联网连接来发布数据。
但是,如果它是用于调整页面大小的脚本,并且用户遇到了一些连接问题(例如,在地铁上访问您的 Web 应用程序),最好已经加载了代码,以便用户可以自由导航。根据我之前发布的 Github 链接:
“经常触发的事件(例如,调整大小/滚动)”
这与性能相关,应进行优化。
将所有代码缩小到一个 JS 文件中以便早期缓存将减少所做的请求数量。此外,建立连接可能需要几秒钟,但处理一堆“if”语句只需要毫秒。
然而,如果您有一个很重的JS文件仅用于一个不是应用程序核心的功能(比如说,这个单独的文件几乎占了其他脚本总和的n%),那么没有必要让用户等待该特定功能。
“如果您的页面媒体内容较多,我们建议研究JavaScript技术,仅在需要时加载媒体资产。”

4

这是JS的圣杯,希望ECMA6/7中的模块可以解决这个问题!

客户端上有像JSPM这样的模块加载器,现在在node.js中也有热交换JS代码编译器,可以通过webpack在客户端使用。

去年我成功地尝试了创建一个简单的应用程序,它只在运行时加载所需的代码/文件块:

这是一个我在github上称为praetor.js的简单测试项目:github.com/magnumjs/praetor.js

gh-pages-code分支可以向您展示它的工作原理:https://github.com/magnumjs/praetor.js/tree/gh-pages-code

在main.js文件中,您可以看到webpackJsonp是如何编译的:

JS:

 module.exports = {
    getPage: function (name, callback) {
        // no better way to do this with webpack for chunk files ?
        if (name.indexOf("demo") !== -1) {
            require(["./modules/demo/app.js"], function (require) {
                callback(name, require("./modules/demo/app.js"));
            });
        }
 .....

要查看其实际效果,请访问http://magnumjs.github.io/praetor.js/,打开网络面板并在左侧的选择菜单中导航时查看运行时加载的块。希望这有所帮助!

1

通常减少HTTP请求是更好的选择,但这要取决于你的Web应用。

我通常使用requirejs在每个文件中包含我需要的正确模型和视图。

在开发中,这样做可以节省我大量的调试时间(因为我知道哪些文件存在),但在生产环境中考虑到请求数量可能会有问题。

因此,在部署时,我使用r.js,它是专门为requirejs设计的,用于编译我的JS文件。

希望这可以帮助到你。


1
谢谢你的回答。使用单个文件意味着一旦第一页加载完成,下一页将不会发出额外的JS代码请求,从而减轻服务器负载并加快页面加载速度。你为什么觉得requirejs有用?你是否测试过比较这些方法的加载速度?谢谢。 - Collector
我编辑了我的回答以提供更多的澄清。 - Lyes BEN
谢谢,但您没有回答我在评论中提出的关于您解决方案的小问题。 - Collector
@Collector 通过只有一个JS文件来减少服务器负载的想法非常模糊。假设您有一个用于验证表单的JS文件,您仅在联系页面中需要它,如果用户永远不会到达联系页面,为什么应该下载它呢?而且不要忘记,require.js的文件也被缓存在浏览器中。 - xpy
如果一个很少使用的功能需要额外的JS代码,比如只有1k左右,那么将其添加到单个大文件中可能是最简单的方法。这也可以确保当需要该功能时,它已经存在,用户不必等待新的连接。总的来说,我认为应该考虑在不同场景下的加载时间和整体开发工作量之间的平衡。谢谢。 - Collector

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接