为什么我需要JavaScript模块加载?所有这些加载程序之间的区别是什么?

为什么我需要JavaScript模块加载?所有这些加载程序之间的区别是什么?,javascript,amd,commonjs,Javascript,Amd,Commonjs,问题1: 为什么我需要在网页中异步加载JavaScript文件?我可以在服务器端看到它的基本原理,但如果我知道需要在客户端加载的所有文件,为什么不将所有源文件连接到一个文件中,然后在页面加载时加载?第一个初始页面加载是否如此重要,以至于将来的操作可能会因为检索每个JS文件的延迟而减慢 问题2: 假设问题1的答案是我需要单独加载JS文件: AMD异步加载每个JS文件,CommonJS同步加载。服务器端加载需要CJS(如果我没弄错的话,Node.js就是这样工作的)。AMD似乎更适合客户。因此,在客

问题1

为什么我需要在网页中异步加载JavaScript文件?我可以在服务器端看到它的基本原理,但如果我知道需要在客户端加载的所有文件,为什么不将所有源文件连接到一个文件中,然后在页面加载时加载?第一个初始页面加载是否如此重要,以至于将来的操作可能会因为检索每个JS文件的延迟而减慢

问题2

假设问题1的答案是我需要单独加载JS文件:

AMD异步加载每个JS文件,CommonJS同步加载。服务器端加载需要CJS(如果我没弄错的话,Node.js就是这样工作的)。AMD似乎更适合客户。因此,在客户机中使用CJS的唯一原因是与服务器共享代码

有没有办法让AMD和CJS玩得很好,这样客户端JS文件可以异步加载,但仍然有CJS语法

(require.js到底做什么?我一辈子都看不懂他们网站上的字里行间。)

你不需要异步加载javascript文件或通过自定义加载程序加载javascript文件。以下是异步加载或自定义加载可能带来好处的一些原因:

  • 通常不需要javascript文件,您可能希望根据需要加载它,而不是一直加载
  • 当初始页面显示不需要javascript文件,并且希望最大化页面的第一次显示速度时
  • 当您想要控制加载javascript文件的确切时间时
  • 当您根据某些条件决定是否加载javascript文件时(例如,如果从CDN加载失败,则可能从备份位置加载)
  • 当您希望脚本加载与其他事情并行进行,而不是一个接一个地序列化时

如果您不需要任何这些好处或编程加载提供的其他好处,那么您可以使用普通的
标记,让它们同步加载。

连接文件的部分问题不是下载所花的时间,而是编译每个页面所花的时间

如果您有一个20000行的文件,并且您只需要其中600行就可以启动并运行所有内容(假设所有内容都是以模块化和异步方式编写的,使用任何模式来管理资源),那么您就可以节省半秒或更长的时间,如果您为核心程序提供服务,并根据需要进行扩展(或者使用延迟计时器,为彼此密切相关的大块功能提供服务)

下载花费的总时间更高。
使用的HTTP连接总数更高。
但使页面对用户可见所需的时间较短。
向页面添加基本功能所需的时间较短。
然后,可以在加载和初始化之后,或者根据用户的请求及时导入额外的功能,并且在这两种情况下,只要您导入的代码专注于做这一件事,而不是调用六个其他依赖项,请求和添加功能之间的时间将是最短的

基本上,RequireJS使用承诺系统

它允许您预先声明依赖项,并在处理完所有依赖项后提交要实现的代码(作为回调)。
如果这些依赖项有任何依赖项,则在加载它们的依赖项之前,不会初始化它们。
如果您只想加载它,并且顺序并不重要,那么您不需要为它提供依赖项

总的来说,如果你有一个系统,你所有的文件都很小,JS在页面上的总重量很小,你只需要几百行就可以完成你想在页面上做的一切。。。另外,你知道你所有的依赖项在哪里,你在服务器上有一个系统来确保它们的顺序正确,等等(另外你有很好的文档,或者你是唯一一个接触到这段代码的人,你每天都生活在其中)。。。 …那么做你正在做的事情没有什么错

如果您发出的HTTP请求数量超过了编译时间,那么您可能根本看不到任何差异。
但对于数十(或数百)行长的应用程序来说,在任何一个页面上都只需要一小部分功能,从页面加载到应用程序“准备就绪”之间的感知时间可以大大节省用于用户的基本交互。

如果要为每个页面加载整个javascript源代码,请将其编译为一个文件。如果根据用户采取的操作或加载的页面加载不同的代码,请使用AMD加载的模块。另一种选择是列出一组脚本标记,当然一次只加载一个,可能需要一段时间

AMD不是一个特定的库,它实际上是加载javascript模块的标准,您提到的大多数加载程序都使用它。这意味着它们都使用类似的语法来定义和加载模块。他们正在考虑将AMD作为ECMA脚本规范的一部分。它的有用之处在于,您还可以定义依赖项,因此,如果您的代码需要运行jQuery,您可以将其列为依赖项,并将其加载到您的模块命名空间中

define( [ 'jquery' ], function ( $ ) {
    // use jquery in here without clouding up the global namespace

    return {}; // return your module for use in a different module or whatever
};
在本例中,在下载jquery模块之前,不会运行已定义模块中的代码。然后,它将jquery模块作为参数直接注入到新定义的模块中

现在,您可以将代码整齐地组织到包含