胖蔡叨叨叨
你听我说

RequireJs 高级用法

从包中加载模块

RequireJS支持加载CommonJS Packages目录结构中的模块,但是需要指定一些其他配置才能使其正常工作。具体来说,它支持以下CommonJS Packages功能:

  • 软件包可以与模块名称/前缀关联。
  • 程序包配置可以为特定程序包指定以下属性:
    • name:程序包的名称(用于模块名称/前缀映射)
    • location:磁盘上的位置。位置相对于baseUrl配置值,除非它们包含协议或以反斜杠(/)开头。
    • main:某人对“ packageName”的要求时应使用的包内模块的名称。默认值为“ main”,因此仅当它不同于默认值时才指定它。该值是相对于包文件夹的。

重要笔记

  • 尽管软件包可以具有CommonJS目录布局,但模块本身应采用RequireJS可以理解的模块格式。规则的例外:如果您使用的是r.js节点适配器,则这些模块可以采用传统的CommonJS模块格式。如果需要将传统的CommonJS模块转换为RequireJS使用的异步模块格式,则可以使用CommonJS转换工具
  • 一次只能在项目上下文中使用软件包的一个版本。您可以使用RequireJS多版本支持来加载两个不同的模块上下文,但是如果要在一个上下文中使用程序包A和B,并且它们依赖于程序包C的不同版本,那么这将是一个问题。将来可能会改变。

如果您使用《入门指南》中指定的类似项目布局,则Web项目的开始将类似于以下内容(基于Node / Rhino的项目是类似的,只需使用scripts目录的内容作为顶级项目目录):

  • 项目目录/
    • project.html
    • 脚本/
      • require.js

这是带有两个包cartstore的示例目录布局的外观:

  • 项目目录/
    • project.html
    • 脚本/
      • 大车/
        • main.js
      • 店铺/
        • main.js
        • util.js
      • main.js
      • require.js

project.html将具有如下脚本标记:

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

这将指示require.js加载脚本/main.js。main.js使用“ packages”配置来设置与require.js相关的软件包,在这种情况下,它们是源文件“ cart”和“ store”:

//main.js contents
//Pass a config object to require
require.config({
    "packages": ["cart", "store"]
});

require(["cart", "store", "store/util"],
function (cart,   store,   util) {
    //use the modules as usual.
});

“ cart”的需求意味着它将从scripts / cart / main.js加载,因为“ main”是RequireJS支持的默认主模块设置。将从scripts / store / util.js加载“ store / util”的需求。

如果“ store”包未遵循“ main.js”约定,则看起来更像这样:

  • 项目目录/
    • project.html
    • 脚本/
      • 大车/
        • main.js
      • 店铺/
        • store.js
        • util.js
      • main.js
      • package.json
      • require.js

然后,RequireJS配置将如下所示:

require.config({
    packages: [
        "cart",
        {
            name: "store",
            main: "store"
        }
    ]
});

为避免冗长,强烈建议始终使用在结构中使用“主要”约定的软件包。

多版本支持

配置选项中所述,可以使用不同的“上下文”配置选项将模块的多个版本加载到页面中。require.config()返回一个使用上下文配置的require函数。这是一个加载两个不同版本的alpha和beta模块的示例(此示例摘自其中一个测试文件):

<script src="../require.js"></script>
<script>
var reqOne = require.config({
  context: "version1",
  baseUrl: "version1"
});

reqOne(["require", "alpha", "beta",],
function(require,   alpha,   beta) {
  log("alpha version is: " + alpha.version); //prints 1
  log("beta version is: " + beta.version); //prints 1

  setTimeout(function() {
    require(["omega"],
      function(omega) {
        log("version1 omega loaded with version: " +
             omega.version); //prints 1
      }
    );
  }, 100);
});

var reqTwo = require.config({
      context: "version2",
      baseUrl: "version2"
    });

reqTwo(["require", "alpha", "beta"],
function(require,   alpha,   beta) {
  log("alpha version is: " + alpha.version); //prints 2
  log("beta version is: " + beta.version); //prints 2

  setTimeout(function() {
    require(["omega"],
      function(omega) {
        log("version2 omega loaded with version: " +
            omega.version); //prints 2
      }
    );
  }, 100);
});
</script>

注意,“ require”被指定为模块的依赖项。这允许传递给函数回调的require()函数使用正确的上下文正确加载模块以支持多版本。如果未将“ require”指定为依赖项,则可能会出现错误。

页面加载后加载代码

上面“ Multiversion支持”部分中的示例显示了以后如何通过嵌套的require()调用来加载代码。

网络工作者支持

从0.12版开始,RequireJS可以在Web Worker中运行。只需在网络工作者中使用importScripts()来加载require.js(或包含require()定义的JS文件),然后调用require。

您可能需要设置baseUrl 配置选项,以确保require()可以找到要加载的脚本。

通过查看单元测试中使用的文件之一,可以看到其用法示例。

犀牛支持§4.5

RequireJS可以通过r.js适配器在Rhino中使用。有关更多信息,请参见r.js自述文件

Nashorn支持

从RequireJS 2.1.16开始,RequireJS可以通过r.js适配器在Java 8+的JavaScript引擎Nashorn中使用。有关更多信息,请参见r.js自述文件

处理错误

错误的一般类别是脚本(未找到),网络超时或所加载脚本中的错误的404。RequireJS有一些用于处理它们的工具:特定于需求的errback,“ paths”数组配置以及全局的requirejs.onError。

传递给errbacks的错误对象和全局requirejs.onError函数通常将包含两个自定义属性:

  • requireType:具有一般分类的字符串值,例如“ timeout”,“ nodefine”,“ scripterror”。
  • requireModules:超时的模块名称/ URL的数组。

如果您在requireModules中遇到错误,则可能意味着未定义依赖于requireModules数组中的模块的其他模块。

捕获IE中的负载故障

Internet Explorer存在一系列问题,使得难以检测到错误/路径后备的加载失败:

  • script.onerror在IE 6-8中不起作用。无法知道加载脚本是否会生成404,更糟糕的是,即使在404情况下,它也会触发具有完整状态的onreadystatechange。
  • script.onerror确实可以在IE 9+中运行,但是存在一个错误,即在执行脚本后不立即触发script.onload事件处理程序,因此它不支持允许匿名AMD模块的标准方法。因此仍使用script.onreadystatechange。但是,在script.onerror函数启动之前,onreadystatechange会以完整状态启动。

因此,使用IE很难同时允许匿名的AMD模块和可靠的检测错误,匿名的AMD模块是AMD模块的核心优势。

但是,如果您知道在一个项目中使用define()声明其所有模块,或者它使用shim config为不使用define()的任何内容指定字符串导出,那么如果您设置了defineDefine配置值确实,加载器可以通过检查define()调用或填充程序的导出全局值的存在来确认脚本是否已加载。

因此,如果要支持Internet Explorer,捕获负载错误并通过直接define()调用或shim config获得模块化代码,请始终将forcedDefine设置为true。有关示例,请参见下一部分。

注意:如果您确实设置了forceDefine:true,并且使用data-main =“”来加载主JS模块,则该主JS模块必须调用define()而不是require()来加载所需的代码。JS主模块仍然可以调用require / requirejs来设置配置值,但是对于加载模块,它应该使用define()。

如果然后您还使用杏仁来构建没有require.js的代码,请确保使用insertRequire构建设置为主模块插入一个require调用-达到与最初的require()调用相同的目的,即调用data-main做。

require([])错误

当与requirejs.undef()一起使用时,Errbacks将允许您检测模块是否无法加载,取消定义该模块,将配置重置到另一个位置,然后重试。

一个常见的用例是使用CDN托管的库版本,但是如果失败,请切换到本地加载文件:

requirejs.config({
    enforceDefine: true,
    paths: {
        jquery: 'http://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min'
    }
});

//Later
require(['jquery'], function ($) {
    //Do something with $ here
}, function (err) {
    //The errback, error callback
    //The error has a list of modules that failed
    var failedId = err.requireModules && err.requireModules[0];
    if (failedId === 'jquery') {
        //undef is function only on the global requirejs object.
        //Use it to clear internal knowledge of jQuery. Any modules
        //that were dependent on jQuery and in the middle of loading
        //will not be loaded yet, they will wait until a valid jQuery
        //does load.
        requirejs.undef(failedId);

        //Set the path to jQuery to local path
        requirejs.config({
            paths: {
                jquery: 'local/jquery'
            }
        });

        //Try again. Note that the above require callback
        //with the "Do something with $ here" comment will
        //be called if this new attempt to load jQuery succeeds.
        require(['jquery'], function () {});
    } else {
        //Some other error. Maybe show message to the user.
    }
});

使用`requirejs.undef()`,如果您稍后设置其他配置并尝试加载相同的模块,则加载器仍会记住哪些模块需要该依赖关系,并在新配置的模块加载时完成加载。

注意:errbacks仅适用于回调样式的require调用,而不适用define()调用。define()仅用于声明模块。

路径配置后备

上面的用于检测负载故障,对模块进行undef(),修改路径和重新加载的模式是一个足够常见的请求,它也有一个简写。路径配置允许使用数组值:

requirejs.config({
    //To get timely, correct error triggers in IE, force a define/shim exports check.
    enforceDefine: true,
    paths: {
        jquery: [
            'http://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min',
            //If the CDN location fails, load from this location
            'lib/jquery'
        ]
    }
});

//Later
require(['jquery'], function ($) {
});

上面的代码将尝试CDN位置,但是如果失败,则退回到本地lib / jquery.js位置。

注意:路径回退仅适用于确切的模块ID匹配。这与可应用于模块ID前缀段的任何部分的常规路径配置不同。后备的目标更多是针对异常错误的恢复,而不是通用的路径搜索路径解决方案,因为它们在浏览器中效率低下。

全局requirejs.onError函数

要检测本地错误未捕获的错误,可以覆盖requirejs.onError():

requirejs.onError = function (err) {
    console.log(err.requireType);
    if (err.requireType === 'timeout') {
        console.log('modules: ' + err.requireModules);
    }

    throw err;
};
赞(0) 打赏
转载请附上原文出处链接:胖蔡叨叨叨 » RequireJs 高级用法
分享到: 更多 (0)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏