Javascript 如何使用RequireJS实现延迟加载?

Javascript 如何使用RequireJS实现延迟加载?,javascript,backbone.js,requirejs,js-amd,Javascript,Backbone.js,Requirejs,Js Amd,我们正在使用主干网、RequireJS和Handlebar构建一个非平凡的web应用程序,我只是好奇。目前,我们的每一款车型都是这样的: define(['Backbone', 'js/thing/a', 'js/thing/b', 'js/lib/bob'], function(a, b, bob) { return Backbone.Router.extend({ // stuff here }); }); 其中,thing/a、thing/b都有自己的依赖项,例如在把手模

我们正在使用主干网、RequireJS和Handlebar构建一个非平凡的web应用程序,我只是好奇。目前,我们的每一款车型都是这样的:

define(['Backbone', 'js/thing/a', 'js/thing/b', 'js/lib/bob'], function(a, b, bob) {
  return Backbone.Router.extend({
    // stuff here
  });
});
其中,thing/a、thing/b都有自己的依赖项,例如在把手模板上,等等。现在发生的是,在my main.js中,所有“顶级”路由器都已加载并初始化;每个顶级路由器都有一组依赖项(模型、视图等),每个依赖项都有自己的依赖项(模板、助手、UTIL等)。基本上是一棵大树

本例中的问题是,整个树在页面加载时被解析和加载。我不介意这样做,因为我们最终将通过优化器运行它,并最终得到一个大文件(将RequireJS简化为基本的模块化框架)。然而,我很好奇你是否可以“按需”加载视图和模板之类的东西

这里解释了“简化的CommonJS包装”,因此我尝试:

define(function(require) {
  Backbone = require('Backbone');
  return Backbone.Router.extend({
    doStuff: function() {
      var MyView = require('js/myView');
      new MyView().render();
    }
  });
});
然而,看看Chrome的网络检查器,似乎RequireJS——不知何故,即使没有触发触发doStuff处理程序的路由——仍然加载
myView
依赖项。问题:

  • 这真的可能吗?在RequireJS中是否有黑色魔法可以在不触发
    doStuff
    路由的情况下查找对
    require()
    的调用
  • 这是“按需”延迟加载RequireJS模块和资源的理论正确方法吗
  • 如果使用此符号,r.js优化器是否仍像广告中那样工作
    • 这真的可能吗?在RequireJS中是否有黑色魔法可以在不触发doStuff路由的情况下寻找对require()的调用?

      当您使用“sugar”语法提取对
      require
      的引用,然后在运行函数之前将它们列为依赖项时。基本上,它成为define的常规样式,第一个参数是dep数组

      因此,它不关心require调用在哪里,这就是为什么条件语句被忽略的原因(它还解释了为什么那些
      require
      调用必须使用字符串文字,而不是变量)

      这是“按需”延迟加载RequireJS模块和资源的理论正确方法吗?

      如您所见,使用sugar语法将不允许条件加载。我脑子里能想到的唯一方法就是使用
      require
      调用和一个dep数组和一个回调:

      define(function(require) {
          var module1 = require('module1');
      
          // This will only load if the condition is true
          if (true) {
              require(['module2'], function(module2) {
      
              });
          }
      
          return {};
      });
      
      mymodule.get().then(function(m) {
          // here m is the real mymodule
      });
      
      唯一的缺点是另一个嵌套函数,但如果您追求性能,那么这是一个有效的路由

      如果使用此符号,r.js优化器是否仍能像广告中那样工作?

      如果您使用的是“sugar”语法,那么是的,乐观主义者会很好地工作。例如:

      模块/test.js

      define(function(require) {
          var $ = require('jquery');
          var _ = require('underscore');
      
          return {
              bla: true
          }
      });
      
      一旦由r.js编译,这看起来像:

      define('modules/test', ['require', 'jquery', 'underscore'], function(require) {
          var $ = require('jquery');
          var _ = require('underscore');
      
          return {
              bla: true
          }
      });
      

      总之,您可以有条件地加载内容,但正如您所提到的,如果您打算使用r.js优化项目,那么仅使用sugar语法不会带来巨大的开销。

      您可能还想查看一下

      它有一个运行时组件和一个构建时组件。运行时组件允许您将模块延迟为(注意
      lazy!
      插件):

      在前面的上下文中,
      mymodule
      是一个,实际模块将加载
      get()
      ,并在
      then()
      回调中可用:

      define(function(require) {
          var module1 = require('module1');
      
          // This will only load if the condition is true
          if (true) {
              require(['module2'], function(module2) {
      
              });
          }
      
          return {};
      });
      
      mymodule.get().then(function(m) {
          // here m is the real mymodule
      });
      
      要求lazy与r.js集成,以自动创建Javascript文件的“捆绑包”。它还自动处理捆绑包的缓存破坏。这里有几个例子可以让你有一个想法。还有一个问题,那就是整合