关键要点
RequireJS是一个用于浏览器的AMD模块加载器,可以异步加载脚本和CSS文件。您不再需要处理单个文件(例如index.html)中脚本文件的顺序。相反,您只需将代码包装在模块定义中,RequireJS将负责依赖项管理,使您的代码结构更清晰,组织更合理。它还有一个优化工具,可以压缩和连接用于生产环境的文件。
官方网站提供了关于其API的详尽文档,并且有很多示例代码库可以帮助您。但是,它有很多配置,一开始使用RequireJS会比较棘手。
在本文中,我们将学习如何通过使用AMD模块构建库、对其进行优化并使用RequireJS优化器将其导出为独立模块来使用RequireJS。稍后,我们将使用RequireJS构建应用程序并使用我们的库。
本教程假设您对RequireJS有一定的了解。如果您正在寻找入门指南,请查看:理解RequireJS以实现有效的JavaScript模块加载。
安装RequireJS
RequireJS可通过bower安装:
<code class="language-bash">bower install requirejs --save</code>
或者您可以从github获取文件。
还有一个基于Grunt的Yeoman生成器用于RequireJS项目。
定义AMD模块
我们将代码包装在define()
中,这将使其成为一个AMD模块。
文件:mylib.js
<code class="language-javascript">define(['jquery'], function($) { // $现在是jquery。 return 'mylib'; });</code>
就是这样。请注意,define()
接受一个可选的第一个参数,即依赖项数组,在本例中为['jquery']
。它是此模块的依赖项列表。数组中的所有模块都将在此模块之前加载。执行此模块时,参数是依赖项数组中的相应模块。
因此,在本例中,将首先加载jQuery,然后将其作为参数$传递到函数中,然后我们可以在模块中安全地使用它。最后,我们的模块返回一个字符串。返回值是在需要此模块时传递给函数参数的内容。
引用其他模块
让我们通过定义第二个模块并引用我们的第一个模块mylib.js来看看它是如何工作的。
文件:main.js
<code class="language-bash">bower install requirejs --save</code>
您可以在依赖项数组中引用任意数量的依赖项,并且所有模块都将按相同的顺序通过函数参数提供。在这个第二个模块中,我们引用了jquery和mylib模块,并简单地返回了一个对象,公开了某些变量。此库的用户将使用此对象作为您的库。
配置RequireJS优化器:r.js
您可能想知道,RequireJS仅通过查看依赖项数组中的字符串如何知道要加载哪个文件?在我们的例子中,我们提供了jquery和mylib作为字符串,RequireJS知道这些模块在哪里。mylib很简单,它是mylib.js,省略了.js。
jquery呢?这就是RequireJS配置的用途。您可以通过RequireJS配置提供广泛的配置。有两种方法可以提供此配置,因为我们使用的是RequireJS优化器,我将向您展示r.js方法。r.js是RequireJS优化器。
我们将向r.js提供一个配置,它将所有模块优化到单个文件中。我们提供的配置将使r.js将模块构建为独立的全局库,既可以作为AMD模块使用,也可以在浏览器中作为全局导出使用。
r.js可以通过命令行或作为Node模块运行。还有一个用于运行优化器的Grunt任务grunt-requirejs。
话虽如此,让我们看看我们的配置是什么样的:
文件:tools/build.js
<code class="language-javascript">define(['jquery'], function($) { // $现在是jquery。 return 'mylib'; });</code>
配置文件实际上是RequireJS的核心。一旦您了解了这些参数的工作原理,您就可以像专业人士一样使用RequireJS。
您可以执行不同的操作,并使用配置文件调整项目构建。要了解有关配置和RequireJS的一般信息,建议您参考文档和wiki。还有一个示例配置文件,演示了如何使用构建系统,因此请务必也参考该文件。
最后,我们实际上运行了优化器。正如我之前所说,您可以通过命令行或Node以及Grunt任务运行它。请参阅r.js自述文件以了解如何在不同的环境中运行优化器。
<code class="language-javascript">define(['jquery', 'mylib'], function($, mylib) { // $照常是jquery // mylib是字符串`mylib`,因为这是第一个模块的返回值 // return { version: '0.0.1, jQuery版本:' + $.fn.jquery, mylibString: mylib } });</code>
这将在dist/mylib.js中生成构建文件
build.js
接下来,让我们看看这些参数的实际含义。
baseUrl – 所有模块查找的根路径。
paths – 相对于baseUrl的模块名称的路径映射。
在我们的示例中,“mylib”映射到“../main”,它相对于baseUrl,因此当我们引用“mylib”时,它加载文件“../lib/../mylib/main.js”。请注意,我们附加了baseUrl,然后是paths设置,然后是模块名称,后跟.js后缀。您可以在其中指定模块如何映射到文件,例如jquery和mylib。
include – 我们想要包含在优化过程中的模块。包含的模块所需的依赖项会隐式包含。在我们的例子中,main模块依赖于mylib和jquery,它们也将被包含在内,因此无需显式包含它。我们还包含稍后将提到的almond。
exclude – 我们想要从优化过程中排除的模块。在我们的例子中,我们排除了jquery。构建库的使用者将提供一个jQuery库。稍后我们将看到这一点。
out – 优化的输出文件的名称。
wrap – 将构建包包装在wrap指定的开始和结束文本中。优化的输出文件如下所示:wrap.start 包含的模块 wrap.end。wrap.start和wrap.end是其内容包含在输出中的文件名称。
almond
构建的库不包含require.js文件,而是使用almond。almond是一个小型AMD API实现,它将替换require.js。
包装我们的库
在r.js配置中,我们使用wrap.start和wrap.end文件包装了我们的库。我们还在库中包含了almond,这些将使我们的库独立,因此它们可以通过浏览器全局变量使用,也可以通过requirejs作为AMD模块使用。
文件:wrap.start
<code class="language-bash">bower install requirejs --save</code>
我们包含的模块main、mylib和almond位于wrap.start和wrap.end的中间。
文件:wrap.end
<code class="language-javascript">define(['jquery'], function($) { // $现在是jquery。 return 'mylib'; });</code>
如果使用者使用AMD加载器,则构建的文件将请求“jquery”作为AMD依赖项。如果使用者只使用浏览器全局变量,则库将获取$全局变量并将其用于jQuery依赖项。
使用RequireJS使用库
我们的库已经完成了,现在让我们通过构建一个requirejs应用程序来实际使用它。
文件:app.js
<code class="language-javascript">define(['jquery', 'mylib'], function($, mylib) { // $照常是jquery // mylib是字符串`mylib`,因为这是第一个模块的返回值 // return { version: '0.0.1, jQuery版本:' + $.fn.jquery, mylibString: mylib } });</code>
这里没有什么特别的,它只是另一个引用jQuery和mylib的模块。当使用define
定义模块时,它不会立即执行,也就是说,它的回调函数(在依赖项数组之后传递)不会立即执行。这意味着我们的应用程序不会仅仅通过定义此模块而启动。现在让我们看看如何配置RequireJS并实际执行这个模块,即我们的应用程序。
为浏览器配置RequireJS
我们将在一个文件中配置RequireJS并执行我们的app模块。不过,也有不同的方法可以做到这一点。
文件:common.js
<code class="language-javascript">{ "baseUrl": "../lib", "paths": { "mylib": "../main" }, "include": ["../tools/almond", "main"], "exclude": ["jquery"], "out": "../dist/mylib.js", "wrap": { "startFile": "wrap.start", "endFile": "wrap.end" } }</code>
baseUrl和paths配置与之前相同。这里附加的配置值是:
shim: 配置传统“浏览器全局”脚本的依赖项和导出,这些脚本不使用define()
来声明依赖项并设置模块值。例如,Backbone不是AMD模块,但它是一个浏览器全局变量,它将Backbone导出到我们已在exports中指定的全局命名空间。在我们的示例中,模块还依赖于jQuery和Underscore,因此我们使用deps指定它。deps数组中的脚本在加载Backbone之前加载,加载后,exports值将用作模块值。
请注意,您也可以在此应用程序项目中使用r.js,这将需要单独的配置。但不要为此感到困惑。我不会详细介绍如何操作,但这与我们对库所做的类似。请参阅示例构建配置以了解更多信息。
require与define
稍后我们将使用require加载模块并立即执行它。有时define和require可能会混淆使用哪个。define定义一个模块,但不执行它,require定义一个模块并执行它——也就是说,它在执行自身之前加载并执行依赖模块。通常,您将有一个require作为主入口模块,它将依赖于通过define定义的其他模块。
加载脚本
通常,您会在index.html中包含所有脚本文件。现在我们使用RequireJS,我们只需要包含RequireJS并指定我们的data-main,它是我们应用程序的入口点。设置配置选项或分离在index.html中使用的主模块的方法有很多种。您可以在此处找到更多信息。
<code class="language-bash">bower install requirejs --save</code>
结论
在本文中,我们使用RequireJS构建了一个库和一个使用该库的应用程序。我们学习了如何配置r.js优化器以及如何在浏览器中配置RequireJS。最后,我们学习了如何使用RequireJS定义和使用AMD模块。这使我们的代码结构良好且组织有序。
在本教程的前半部分(配置优化器),我使用了这个example-libglobal存储库,后半部分并不复杂,因此您现在应该能够自己动手了。
官方RequireJS网站是最终文档,但请务必查看github上的示例存储库以及该存储库中的示例项目,这些项目演示了RequireJS应用程序的使用。
关于使用RequireJS构建库的常见问题解答(FAQ)
RequireJS在JavaScript开发中的主要目的是什么?
RequireJS是一个JavaScript文件和模块加载器。它针对浏览器使用进行了优化,但也可以在其他JavaScript环境中使用。RequireJS的主要目的是鼓励在JavaScript中使用模块化编程。它帮助开发人员管理JavaScript文件之间的依赖关系并模块化其代码。这导致更好的代码组织、可维护性和可重用性。它还可以提高代码的速度和质量。
RequireJS如何处理JavaScript文件依赖关系?
RequireJS使用异步模块定义 (AMD) API 来处理 JavaScript 模块。这些模块可以异步加载,这意味着它们不会阻塞其他脚本在加载时运行。当您使用 RequireJS 定义模块时,您会指定其依赖项。然后,RequireJS 会确保在模块本身之前加载这些依赖项。
如何使用RequireJS定义模块?
要在RequireJS中定义模块,您可以使用define()
函数。此函数接受两个参数:一个依赖项数组和一个工厂函数。依赖项是模块所依赖的文件的路径。工厂函数是您编写模块代码的地方。一旦所有依赖项都加载完毕,就会调用此函数。
如何在代码中使用用RequireJS定义的模块?
要使用用RequireJS定义的模块,您可以使用require()
函数。此函数接受两个参数:一个依赖项数组和一个回调函数。依赖项是您要使用的模块的路径。回调函数是您使用模块的地方。一旦所有模块都加载完毕,就会调用此函数。
我可以将RequireJS与其他JavaScript库(如jQuery)一起使用吗?
是的,您可以将RequireJS与其他JavaScript库(如jQuery)一起使用。RequireJS有一个内置功能,用于加载不使用define()
来声明依赖项并设置模块值的传统非模块化脚本,称为“shim”。使用shim,您可以为不使用define()
来声明依赖项和设置模块值的脚本指定依赖项和导出。
如何使用RequireJS优化我的代码?
RequireJS带有一个名为r.js的优化工具。此工具将您的JavaScript文件及其依赖项组合并压缩到单个文件中。这减少了HTTP请求的数量和文件的大小,这可以大大提高网页的加载时间。
RequireJS中define()和require()的区别是什么?
define()
函数用于定义模块,而require()
函数用于加载模块。这两个函数都接受一个依赖项数组和一个函数作为参数。但是,传递给define()
的函数用于创建模块值,而传递给require()
的函数用于在模块加载后运行代码。
我可以在Node.js中使用RequireJS吗?
是的,您可以在Node.js中使用RequireJS。但是,Node.js有自己的模块系统,因此您可能不需要RequireJS。如果您想在浏览器和Node.js中都使用相同的代码,或者如果您更喜欢AMD API,那么RequireJS可能是一个不错的选择。
如何处理RequireJS中的错误?
RequireJS提供了一个onError
回调来处理错误。当加载模块时出现错误时,会调用此回调。您可以使用此回调来记录错误或从中恢复。
我可以使用RequireJS加载CSS文件吗?
是的,您可以使用require-css插件使用RequireJS加载CSS文件。此插件允许您加载和等待CSS文件,就像您使用JavaScript模块一样。
以上是用requirej构建图书馆的详细内容。更多信息请关注PHP中文网其他相关文章!