data-main和普通脚本加载的区别

26
使用RequireJS时,使用的方式来包含脚本有何不同?
<script data-main="scripts/main" src="scripts/require.js"></script>

并且

<script src="scripts/require.js"></script>

即:什么是data-main属性在加载脚本方面的变化?我已经阅读了相关文档,但是其中的区别并不完全清晰。
引用块:

通常情况下,您将使用一个data-main脚本来设置配置选项,然后加载第一个应用程序模块。注意:require.js为您的data-main模块生成的脚本标记包括async属性。这意味着,您不能假定您的data-main脚本的加载和执行会在同一页面后引用的其他脚本之前完成。

文档提到您通常会使用一个data-main脚本来设置配置选项和加载第一个应用程序模块 - 但是您不也可以通过普通的script标签来实现吗?使用data-main属性加载应用程序模块的配置是否有好处? data-main的唯一区别是异步加载吗?还是有其他区别?

是的,文档不太好,“通常会使用…”,但他们没有解释为什么。 - kiwicomb123
4个回答

30

data-main只是执行应用程序的初始require调用的另一种方式。为了说明这一点:

<script data-main="scripts/main" src="scripts/require.js"></script>

等同于以下内容:

<script src="scripts/require.js"></script>
<script>require(["scripts/main"])</script>

这两种形式都是异步的。其实就是这样。考虑到你有几个入口点或者RequireJS配置将被放置在哪里等因素,与使用data-main没有任何关系。换句话说,这些考虑因素在使用data-main与使用require(["scripts/main"])时发挥的作用是完全相同的。

你引用的文档部分只是通过提到使用data-main加载的脚本在元素中创建了带有async属性设置的


谢谢 @Louis -- 正是我想要的澄清! - Alana Storm

5

data-main是为了让你的应用有一个单一入口点。这一行代码将会加载RequireJS和scripts/main.js,并启动你的应用程序。

这个操作的结果是:

<script data-main="scripts/main" src="scripts/require.js"></script>

在运行时,<script async src="scripts/main.js"></script> 将被添加到文档中。这是包含你的 require.config() 代码块并且拉取你的第一个应用程序脚本的脚本。如果你未指定 data-main,那么除非你显式地加载配置文件和第一个模块,否则仅加载 Require 而不加载你的任何应用程序脚本。
如果没有告诉 Require 加载任何东西,你认为 Require 会加载什么?
如果你不使用 data-main,你必须在加载 Require 之后提供一个入口点(出于没有好的理由,我一直这样做,就是因为我是这样学的)。阅读 配置选项 以查看如何执行此操作。
我在开发中使用这个模式
<script src="js/lib/require.js"></script>
<script src="js/config.js"></script>
<script>
  // same as data-main
  require.config({baseUrl : 'js'});
  require(['js/main']);
</script>

作为一个单一的入口点,config.js 的内容以及随后的 require(['js/main']) 调用将会出现在被引用为 data-main 的脚本中。
如果您使用静态优化器来构建生产包,那么这些都不重要,因为您只需要加载该包即可。

3

data-main是require.js将要处理的脚本。正如文档所说,通常在该脚本中设置配置选项。但还有其他方法来实现这一点。在许多情况下,这是最简单和最有效的地方。但并非总是如此。

由data-main指向的脚本还将列出文件定义的代码的依赖项。依赖关系是重点。通常情况下,第一个模块会加载并执行最终的应用程序。

针对评论的补充说明:

有一些概念需要您了解,这将有助于理解这种方法。

首先,没有单个(或一对,甚至几个)脚本。这种类型的加载器旨在处理大量非常小的脚本。每个脚本都具有非常特定且通常(最好)具有单一目的。将这些脚本称为模块(或单元)。

任何给定的模块可能依赖于任意数量的其他模块才能正常工作。AMD模式允许在每个模块的定义中列出该模块的依赖项。

RequireJS将确定谁需要什么以及以什么顺序,并且在所有依赖项加载并准备就绪之前不会让脚本执行。

因此,这与我们成长过程中在页面中放置脚本链接(或多个链接)的做法完全不同。这是一种非常不同的JavaScript开发方法。一旦您理解了它,并找出如何将代码分解为离散的功能单元,它真的很棒。


谢谢您的回复,我很感激,但这和手册一样令人困惑。显然,您已经内化了一些知识,而我由于没有您的背景而无法理解。为什么使用require.js处理data-main以加载文件与通过正常浏览器手段加载文件有所不同?它是异步加载吗?还是有其他更多的东西?(我对此感兴趣的是在实现层面上,而不仅仅是用户程序员) - Alana Storm
请查看扩展答案。希望我已经透露了一些内部知识。 - DFriend

2
<script data-main="scripts/main.js" src="scripts/vendor/requirejs/require.js"></script>

src会首先加载"scripts/vendor/requirejs/require.js"。然后data-main属性将执行"scripts/main.js"。

最初的回答

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