是否有任何可提供与 Node 相同的灵活性/module化/易用性的浏览器内 JavaScript 库require
?
提供更多细节:原因require
如此之好是它:
- 允许从其他位置动态加载代码(在我看来,这比在 HTML 中链接所有代码在风格上更好)
- 它为构建module提供了一致的接口
- module很容易依赖其他module(例如,我可以编写一个需要 jQuery 的 API,以便我可以使用
jQuery.ajax()
- 加载的 javascript 是有范围的,这意味着我可以加载
var dsp = require("dsp.js");
并且我将能够访问dsp.FFT
,这不会干扰我的本地var FFT
我还没有找到一个有效地做到这一点的图书馆。我倾向于使用的解决方法是:
coffeescript-concat -- 需要其他 js 很容易,但是你必须编译它,这意味着它不太适合快速开发(例如在测试中构建 API)
RequireJS——它很流行、简单明了,可以解决 1-3 个问题,但缺乏范围界定是一个真正的交易破坏者(我相信head.js的相似之处在于它缺乏范围界定,尽管我从来没有机会使用它。类似地,LABjs可以加载并缓解
.wait()
依赖问题,但它仍然不进行范围界定)
据我所知,javascript 的动态和/或异步加载似乎有很多解决方案,但它们往往具有与仅从 HTML 加载 js 相同的范围问题。最重要的是,我想要一种加载 javascript 的方法,它根本不会污染全局命名空间,但仍然允许我加载和使用库(就像节点的 require 那样)。
2020 年更新: module现在是 ES6 的标准,到 2020 年中期,大多数浏览器都原生支持。module支持同步和异步(使用 Promise)加载。我目前的建议是,大多数新项目应该使用 ES6 module,并使用转译器为旧浏览器回退到单个 JS 文件。
作为一般原则,今天的带宽通常也比我最初提出这个问题时宽得多。因此,在实践中,您可能会合理地选择始终使用带有 ES6 module的转译器,并将精力集中在代码效率而不是网络上。
以前的编辑(或者如果你不喜欢 ES6 module):自从写这篇文章以来,我广泛使用了RequireJS(现在有更清晰的文档)。在我看来,RequireJS 确实是正确的选择。我想澄清一下系统如何为和我一样困惑的人工作:
您可以require
在日常开发中使用。module可以是函数(通常是对象或函数)返回的任何内容,并作为参数限定范围。您还可以将项目编译为单个文件以供部署使用r.js
(实际上这几乎总是更快,即使require
可以并行加载脚本)。
RequireJS 和像 browserify(tjameson 推荐的一个很酷的项目)使用的 node-style require 之间的主要区别在于module的设计和需要的方式:
- RequireJS 使用 AMD(异步module定义)。在 AMD 中,
require
需要加载一个module列表(javascript 文件)和一个回调函数。当它加载了每个module时,它会调用回调,并将每个module作为回调的参数。因此它是真正异步的,因此非常适合网络。 - Node 使用 CommonJS。在 CommonJS 中,
require
是一个阻塞调用,它加载一个module并将其作为一个对象返回。这对 Node 很有效,因为文件是从文件系统读取的,这足够快,但在 Web 上效果不佳,因为同步加载文件可能需要更长的时间。
在实践中,许多开发人员在看到 AMD 之前就使用了 Node(因此也使用了 CommonJS)。此外,许多库/module是为 CommonJS(通过向exports
对象添加东西)而不是为 AMD(通过从define
函数返回module)编写的。因此,很多从 Node 转为 Web 的开发人员都希望在 Web 上使用 CommonJS 库。这是可能的,因为从<script>
标签加载是阻塞的。像 browserify 这样的解决方案采用 CommonJS (Node) module并将它们包装起来,以便您可以将它们包含在脚本标签中。
因此,如果您正在为 Web 开发自己的多文件项目,我强烈推荐 RequireJS,因为它确实是一个用于 Web 的module系统(尽管坦率地说,我发现 AMD 比 CommonJS 更自然)。最近,区别变得不那么重要了,因为 RequireJS 现在允许您基本上使用 CommonJS 语法。此外,RequireJS 可用于在 Node 中加载 AMD module(尽管我更喜欢node-amd-loader)。