RequireJS 2.0 API之配置项



§ 2

 

RequireJS 把每一个依赖项当做一个script标签,使用 head.appendChild()来加载。

RequireJS 会计算好依赖关系,按照正确的顺序依次加载所有依赖项。然后才调用模块的构造函数。 

在能同步加载模块的服务端JS中使用 RequireJS 也很容易,只需要重定义require.load()。可以用构建系统来做这个,服务端的 require.load 方法在build/jslib/requirePatch.js 中。

未来,这个代码可能会被当作一个可选的模块放到 require/ 目录中。这样你就可以在基于主机环境来使用正确的加载模式。

 

配置项§ 3

当我们在顶层页面(或者没有定义一个模块的顶层脚本文件)中使用 require() ,可以使用配置对象来进行配置:

[javascript] view plain copy
  1. <script src="scripts/require.js"></script>  
  2. <script>  
  3.   require.config({  
  4.     baseUrl: "/another/path",  
  5.     paths: {  
  6.         "some""some/v1.0"  
  7.     },  
  8.     waitSeconds: 15  
  9.   });  
  10.   require( ["some/module""my/module""a.js""b.js"],  
  11.     function(someModule,    myModule) {  
  12.         //This function will be called when all the dependencies  
  13.         //listed above are loaded. Note that this function could  
  14.         //be called before the page is loaded.  
  15.         //This callback is optional.  
  16.     }  
  17.   );  
  18. </script>  

并且,你可以在require.js加载前定义一个全局的require对象,它会在require.js加载后自动应用于配置。下面的例子定义了一些依赖项,一旦require()方法调用,他们就会加载:

[javascript] view plain copy
  1. <script>  
  2.     var require = {  
  3.         deps: ["some/module1""my/module2""a.js""b.js"],  
  4.         callback: function(module1, module2) {  
  5.             //This function will be called when all the dependencies  
  6.             //listed above in deps are loaded. Note that this  
  7.             //function could be called before the page is loaded.  
  8.             //This callback is optional.  
  9.         }  
  10.     };  
  11. </script>  
  12. <script src="scripts/require.js"></script>  

注意: 最好这样写 var require = {} 而不要这样写 window.require = {}, 因为后者在IE下运行不正确。

支持的配置项:

baseUrl: 查找所有模块的根路径。所以,在上面第一个例子中,"my/module"的 script 标签 src="/another/path/my/module.js"。加载普通.js文件的时候, baseUrl 将不会起作用,script的src会直接使用 那些字符串,所以 a.js 和 b.js 会从HTML页面的同级目录中加载。

如果没有明确的配置 baseUrl ,它的默认值是会是加载require.js的HTML页面所在目录。如果使用 了data-main ,那么baseUrl会被设置成data-main指定的脚本所在目录。

baseUrl 可以与加载 RequireJS 的页面是不同域。  RequireJS 是可以加载跨域脚本的。 唯一的例外是,使用text! 插件加载的文本模块:这些路径必须与页面是在同一个域下,至少在开发的时候是这样的。当使用了 优化工具 后,跨域的文本模块会被打包进来,这时就加载跨域的文本模块了。

paths: 映射到不能直接在baseUrl下找到的模块名。 通常, path 设置的路径是相对于 baseUrl 的,除非 以 "/" 开头或包含URL协议 (例如" http:")。例如上例中,"some/module" 模块的最终生成的script标签的src="/another/path/some/v1.0/module.js"。 path的设置不要加.js后缀,因为path也可能是映射到一个目录。 如果path映射的是一个模块,RequireJS会自动加上.js后缀。

shim: 为那些没有使用 define() 声明依赖项、没有设置模块值、老的、传统的"浏览器全局"脚本配置依赖项和exports。例如 (RequireJS 2.1.0+):

requirejs.config({
    shim: {
        'backbone': {
            //These script dependencies should be loaded before loading
            //backbone.js
            deps: ['underscore', 'jquery'],
            //Once loaded, use the global 'Backbone' as the
            //module value.
            exports: 'Backbone'
        },
        'foo': {
            deps: ['bar'],
            exports: 'Foo',
            init: function (bar) {
                //Using a function allows you to call noConflict for
                //libraries that support it, and do other cleanup.
                //However, plugins for those libraries may still want
                //a global. "this" for the function will be the global
                //object. The dependencies will be passed in as
                //function arguments. If this function returns a value,
                //then that value is used as the module export value
                //instead of the object found via the 'exports' string.
                return this.Foo.noConflict();
            }
        }
    }
});

//Then, later in a separate file, call it 'MyModel.js', a module is
//defined, specifying 'backbone' as a dependency. RequireJS will use
//the shim config to properly load 'backbone' and give a local
//reference to this module. The global Backbone will still exist on
//the page too.
define(['backbone'], function (Backbone) {
  return Backbone.Model.extend({});
});

在RequireJS 2.0.* 中, shim 中的"exports" 属性也可以配置成一个函数。这种情况, 它的功能和上面的 "init" 属性一样。  "init" 属性用于RequireJS 2.1.0+ 中,如此, exports配置的字符串值可用于 enforceDefine,也可用于类库加载后的一些功能性工作。

像 jQuery 或者 Backbone 插件这种不需要导出一个模块值的模块,可以用 shim 只配置一个表示依赖项的数组:

requirejs.config({
    shim: {
        'jquery.colorize': ['jquery'],
        'jquery.scroll': ['jquery'],
        'backbone.layoutmanager': ['backbone']
    }
});

然而如果你想要在IE中检测404并执行fallbacks 或者errbacks,那么就必须配置 exports ,这样加载器才能检测脚本是否加载成功:

requirejs.config({
    shim: {
        'jquery.colorize': {
            deps: ['jquery'],
            exports: 'jQuery.fn.colorize'
        },
        'jquery.scroll': {
            deps: ['jquery'],
            exports: 'jQuery.fn.scroll'
        },
        'backbone.layoutmanager': {
            deps: ['backbone']
            exports: 'Backbone.LayoutManager'
        }
    }
});

关于"shim"配置项的重要注意事项:

  • shim只是配置模块的依赖关系。需要加载 模块的话,还是需要用 调用require/define 。 设置shim不会触发加载代码。
  • 确保"shim"配置的模块只当另外一个"shim"配置的模块或者没有依赖关系的AMD模块的依赖模块,并且在在他们创建一个全局变量后调用define()(比如 jQuery ,lodash)。 另外,如果你使用一个 AMD 模块当shim配置的模块的依赖项,打包后, 那个AMD模块在shim配置的模块代码运行前可能不会被赋值 ,并且会抛出一个错误。 最终的解决方案是升级shim配置的模块的代码,加一个可选的 AMD define() 调用。

优化工具配置中的 "shim" 的重要注意事项:

  • 你需要在 mainConfigFile打包配置 中指定shim配置项所在的配置文件。 否则,优化工具找不到 shim 配置。 另一种做法是在打包的配置文件中保留shim配置的副本。
  • 不要在shim配置中混合使用 CDN 加载。 案例:你从CDN加载jQuery,但从本地加载依赖jQuery的Backbone 。当你打包的时候,确保内置jQuery到打包的文件中并且不要从CDN加载。否则,Backbone也会被内置到打包的文件并且在 从CDN加载的jQuery加载前执行。 这是因为shim配置的模块只是延时到依赖模块加载完后再加载, 但是不会自动的使用define包装。 打包后,Backbone 内置了,而来自CDN的jQuery不会被内置,Backbone 会在jQuery加载前、文件加载后执行,而不能在依赖模块jQuery加载后再执行define包装的代码。 define()包装的模块可以与 CDN加载的代码一起使用,因为这些模块正确的使用了define工厂函数进行了包装,这使得他们在依赖项加载前是不会执行的。总结: shim配置是一个为了解决非模块代码,历史代码的方法。 用define()包装的模块更好。
  • 如果你使用uglifyjs来压缩你的代码,不要设置uglifyjs的配置项toplevel 为 true,或者在用命令行的时候不要使用参数-mt。 这些方法会破坏shim需要使用的全局变量名。
  • map: 对于给定的相同的模块名,加载不同的模块,而不是加载相同的模块。

    这种特性在某些大型项目是非常有用的。例如那种有两套不同的模块依赖两个不同版本的'foo'模块,并且这两套模块需要相互协作。

    这时 使用context配置来支持多版本模块加载 是不行的。这种情况下,  paths config 只能设置模块的根路径,而不是映射一个模块到另一个。

    map 的例子:

    requirejs.config({
        map: {
            'some/newmodule': {
                'foo': 'foo1.2'
            },
            'some/oldmodule': {
                'foo': 'foo1.0'
            }
        }
    });
    

    如果模块在硬盘上的结构是这样:

    • foo1.0.js
    • foo1.2.js
    • some/
      • newmodule.js
      • oldmodule.js

    在'some/newmodule' 模块中 `require('foo')` 时,加载的是 foo1.2.js ,当 'some/oldmodule' 模块中 `require('foo')` 时,加载的是 foo1.0.js。

    这个特性只在使用 define()包装的AMD模块时才有效,并且必须是匿名模块。

     map的值也可以是"*",表示全匹配,即所有模块遵循这一设置。如果还有其他匹配项,将会比"*"的配置优先级高。例如:

    
    requirejs.config({
        map: {
            '*': {
                'foo': 'foo1.2'
            },
            'some/oldmodule': {
                'foo': 'foo1.0'
            }
        }
    });
    

    `require('foo')` 时,除了"some/oldmodule" 中会加载 "foo1.0", 其他模块都加载"foo1.2" 。

    config: 传递一个配置信息到模块中是一个常见的需求。这个配置信息通常是应用的一部分,我们需要把它传递到模块中。 在 RequireJS 中,requirejs.config()中的config 配置项 就是为了解决这个需求。 模块中可以通过内置依赖模块"module" ,通过调用module.config()方法来获取传递进来的配置信息。例如:

    requirejs.config({
        config: {
            'bar': {
                size: 'large'
            },
            'baz': {
                color: 'blue'
            }
        }
    });
    
    //bar.js, which uses simplified CJS wrapping:
    //http://requirejs.org/docs/whyamd.html#sugar
    define(function (require, exports, module) {
        //Will be the value 'large'
        var size = module.config().size;
    });
    
    //baz.js which uses a dependency array,
    //it asks for the special module ID, 'module':
    //https://github.com/jrburke/requirejs/wiki/Differences-between-the-simplified-CommonJS-wrapper-and-standard-AMD-define#wiki-magic
    define(['module'], function (module) {
        //Will be the value 'blue'
        var color = module.config().color;
    });
    

    packages: 配置从CommonJS 包来加载模块。详见 packages topic

    waitSeconds: 放弃加载脚本前的等待的秒数。 设置为 0 则禁用此功能。默认是 7 秒。

    context: 加载上下文配置(require.config的对象)的名字。 只要顶级 require调用指定一个唯一context字符串,require.js就可以在一个页面中加载多个版本的模块。要正确的使用它,参考 Multiversion Support 。

    deps: 需要加载的依赖项的数组。当在require.js加载前使用全局 require对象来定义配置的时候很有用,也可以在require()一定义后就马上加载指定依赖项的时候用。

    callback: 所有依赖项加载后执行的回调函数。 当在require.js加载前使用全局 require对象来定义配置的时候很有用,也可以用在require.config中

    enforceDefine: 如果设置为true, 当加载的脚本是没用define()包装过,且在shim配置中没有配置exports值时会抛错。 详见 Catching load failures in IE 。

    xhtml: 如果设置为 true,requireJS 将使用document.createElementNS() 来创建script标签。

    urlArgs:RequireJS 用来匹配资源的额外的 URL的查询参数 。通常的用法是在浏览器或者服务器配置不对的时候禁用缓存。例如:

    urlArgs: "bust=" +  (new Date()).getTime()
    

    这在开发的时候很有用,但是在部署的时候最好删除它。

    scriptType:  设置 RequireJS生成的 script 标签的 type属性值。默认是"text/javascript"。 可设置为"text/javascript;version=1.8" 来使用Firefox's JavaScript 1.8特性。

展开阅读全文

没有更多推荐了,返回首页