RequireJS 需求
- 顺应浏览器机制§ 1
- 在页面加载前后加载代码§ 2
- 脚本应该能够指定依赖项§ 3
- 加载器应该能够加载嵌套依赖项§ 4
- 需要根据依赖项评估模块§ 5
- 模块格式应该简洁§ 6
- 拥有精简的核心加载器,但要为未来做好准备§ 7
- 允许模块保持干净的全局命名空间§ 8
- 加载任何脚本§ 9
- 允许性能升级§ 10
顺应浏览器机制§ 1
XMLHttpRequest(XHR) 加载器仅限于与页面相同的域,并且会使调试更加困难。某些浏览器允许跨域 XHR 调用,并在使用 eval 时提供更好的调试约定,但不同浏览器之间的支持不一致。
应该避免基于 Eval 的加载器,因为 eval 不是 JavaScript 最佳实践,并且在某些环境中是不允许的。Eval 有其适用场景,但模块加载器可以做得比使用它更好。
也不需要动态转换脚本的服务器进程。让每个人都使用相同的服务器进程,甚至为它们可以发出的通用格式制定规范,都会增加开销和编写工作量。前端开发人员长期以来一直能够编写纯文本文件,并让它们在浏览器中加载,而无需大量服务器硬件。
通过脚本标签加载的脚本在任何地方都可以工作,并且可以跨域工作。这是一种更简单的加载方式,它利用了浏览器加载脚本的自然方式。
在页面加载前后加载代码§ 2
相同的系统应该可以在页面加载前后使用。将代码的加载延迟到以后的页面操作是提高性能的关键。
脚本应该能够指定依赖项§ 3
一个项目很容易超出需要几个脚本的范围。手动跟踪所有依赖项和正确的加载顺序非常困难。脚本应该能够指定其直接依赖项。开发人员不必担心这些依赖项需要加载什么,也不必担心如何确定正确的加载顺序。
加载器应该能够加载嵌套依赖项§ 4
如果每个模块都指定了自己的直接依赖项,则加载器应该能够计算出整个系统中正确的依赖项,甚至是嵌套依赖项,以及依赖项的依赖项。
脚本可以无序评估,但需要根据依赖项评估模块§ 5
使用具有嵌套依赖项解析并在页面加载后工作的浏览器原生脚本加载意味着至少部分时间需要通过使用 appendChild 为脚本元素加载脚本。
IE 和 WebKit 将按 DOM 顺序以外的顺序执行通过 appendChild 添加的脚本,它们按网络接收顺序执行这些脚本。即使它们按添加到 DOM 的顺序执行脚本,也会在加载模块脚本后发现模块的依赖项,因此依赖项的脚本将始终在需要它们的脚本之后添加。
这导致为脚本构建模块格式,将脚本的大部分内容放在一个函数中,并在该函数包装器之外指定其依赖项。这允许浏览器无序地评估脚本,但有机会正确地计算出依赖项,然后以正确的顺序调用函数包装器,从而生成脚本。
模块格式应该简洁§ 6
样板代码很麻烦。但是,需要将函数包装器作为样板代码的一部分。最好使样板代码尽可能简洁,以便开发人员可以轻松地手动编码。避免使用对每个属性都使用名称/值对的过于明确的模块格式,因为开发人员必须手动编写这些代码。
拥有精简的核心加载器,但要为未来做好准备§ 7
加载器的核心,即支持嵌套依赖项解析的模块格式,应该简洁,但允许插件扩展依赖项的概念及其加载方式。
在 Dojo 中,通常需要 i18n 字符串包和用于小部件构造的 HTML 文本字符串。允许加载器加载这些内容,但作为插件,因此核心保持轻量级。
允许模块保持干净的全局命名空间§ 8
随着项目规模的扩大,在页面中加载模块的两个版本变得越来越常见。通过允许模块系统不在全局命名空间中定义模块,可以实现这一点。
如果模块想要使用全局命名空间,通常很容易在模块规范中允许这样做。比较困难的部分是构建一种格式,该格式可以很好地避免全局命名空间。
加载任何脚本§ 9
并非所有脚本都将使用模块格式。允许加载现有脚本并将其视为依赖项。
允许性能升级§ 10
这主要意味着拥有一个可以组合和优化模块的构建系统。这也意味着加载器应该允许加载在其中定义了多个模块的脚本,并且只获取该脚本文件中尚未包含的依赖项。