RequireJS - 手动将一些库捆绑在一起

时间:2013-11-04 19:33:12

标签: requirejs

我正在尝试迁移网站以使用RequireJS来管理它的JS依赖项。我还想把一些lib捆绑在一起。

目前我们正在构建一个包含下划线,jquery,bootstrap和骨干的base.min.js。它们在我们的网站上使用,因此将它们组合在一起是有意义的。

尽管如此,我认为我们应该逻辑上将三个库按名称分开,因此我编写了以下require.config:

  require.config({
     baseUrl: '/s/js/libs',
     paths: {
       app: '../app', shims: '../shims'
     },
     map: {
       '*' : {
       // underscore, backbone, jquery and bootstrap are bundled
       'underscore': '../base',
       'backbone': '../base',
       'jquery': '../base',
       'bootstrap': '../base'
        }
     },
     shim:{
        'bootstrap': {
           deps: ['jquery']
        },
        'backbone': {
           deps: ['underscore', 'jquery'],
           exports: 'Backbone'
        },
        'underscore': {
            exports: '_'
        },
        'jquery': {exports: '$'}
      }
  });

我没有使用data-main;但相反,我需要几件事:

  require(["jquery", "underscore", "backbone", "bootstrap", "../baseapp"],
     function($){
       // Next line fixes the bootstrap issue with double modals taken from:
       // http://stackoverflow.com/questions/13649459/twitter-bootstrap-multiple-modal-error
       $.fn.modal.Constructor.prototype.enforceFocus = function () {};
       $('.modal').on('shown', function () {
         $('input:text:visible:first, textarea:visible:first', this).focus();
       });
       $('#search').on('shown', function () {
         $('#id_asf-text').focus();
       })

       require(['micro', 'csrf_xhr', 'locale']);
       require(['app/routers']);

     });

然而,这会导致$未定义的错误。

定义了全局window.$,但似乎requirejs未使用我的垫片exports正确检测到它。即使我exports: 'window.jQuery'它也不起作用。

这是RequireJS中的错误还是我的代码中有错误? mapshim一起玩得很好吗? RequireJS是否支持我的用例?

更新2013-11-05

经过长时间的调试后,我发现在RequireJS中每个“真实”模块都记录了垫片;所以,如果我只是改变我的垫片:

 shim : {
    '../base': {init: function() {return [$, _, Backbone]}}
 }

我确实将此数组作为回调的第一个参数。但是我希望它们能够爆炸,即;将每个返回的值作为参数...

我认为内部地图+路径可行。像这样:

  var require = {
     baseUrl: '/s/js/libs/',
     paths: {
       app: '../app',
       shims: '../shims',

       'base-underscore': '../base',
       'base-backbone': '../base',
   'base-jquery': '../base',
   'base-bootstrap': '../base'
     },
     map: {
       '*' : {
       // underscore, backbone, jquery and bootstrap are bundled
       'underscore': 'base-underscore',
       'backbone': 'base-backbone',
       'jquery': 'base-jquery',
       'bootstrap': 'base-bootstrap',
        }
     },
     shim:{
        'base-bootstrap': {
           deps: ['base-jquery'],
           init: function() {return null}
        },
        'base-backbone': {
           deps: ['base-underscore', 'base-jquery'],
           init: function() {return window.Backbone;}
        },
        'base-underscore': {
           init: function() {return window.Underscore;}
        },
        'base-jquery': {
          init: function() {return $}
        }
     }  // shims
  };

不幸的是,事实并非如此。现在错误是:Uncaught Error: Load timeout for modules: base-underscore,base-backbone,base-bootstrap,../base ...注意没有列出base-jquery!

1 个答案:

答案 0 :(得分:0)

我找到了一个解决方法,但涉及一个插件。这是我目前的解决方案。在我的HTML上,我有以下config(我改为require = {...}成语,以便调试更容易):

  var STATIC_URL = "/s/js/libs/";
  var require = {
     baseUrl: STATIC_URL,
     paths: {
       app: '../app',
       shims: '../shims',
     },
     map: {
       '*': {
            'jquery': 'bundler!jQuery',
            'bootstrap': 'bundler!',
            'underscore': 'bundler!_',
            'backbone': 'bundler!Backbone'
        }
     },
     bundler: {url: '../base'}
  };

bundler.js插件位于我的js/libs。这是最初的CoffeeScript:

global = @

each = (ary, func) ->
    if (ary)
        i = 0
        while i < ary.length and (what = ary[i]) and func(what, i, ary)
            i += 1

getGlobal = (value) ->
    if not value
        value
    g = global;
    each value.split('.'), (part) ->
        g = g[part]
    g

define
    load: (name, require, onload, config) ->
        base = config.bundler?.url ? '../base'
        require [base], () ->
            if name? and name
                value = getGlobal(name)
                onload(value)
            else
                onload()

    normalize: (name, norm) -> name

可能有一种方法可以在没有bundler的情况下执行此操作...我会暂时保持问题,以便提供更好的答案。