Вопрос по javascript – Как добиться ленивой загрузки с RequireJS?

60

Мы создаем нетривиальное веб-приложение с использованием Backbone, RequireJS и Handlebars, и мне просто любопытно. На данный момент каждая из наших моделей Сорта выглядит так:

define(['Backbone', 'js/thing/a', 'js/thing/b', 'js/lib/bob'], function(a, b, bob) {
  return Backbone.Router.extend({
    // stuff here
  });
});

where thing / a, thing / b оба имеют свои собственные зависимости, например от шаблонов Handlebars и т. д. Теперь происходит то, что в моем main.js все маршрутизаторы верхнего уровня загружаются и инициализируются; каждый маршрутизатор верхнего уровня имеет набор зависимостей (модели, представления и т. д.), каждый из которых имеет свои зависимости (шаблоны, помощники, утилиты и т. д.). В основном, большая древовидная структура.

Проблема в этом случае в том, что все это дерево разрешается и загружается при загрузке страницы. Я не возражаю против этого, так как в конечном итоге мы пропустим его через оптимизатор и в результате получим один большой файл (сокращая 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 черные магии, которые ищут вызовыrequire() фактически не вызываяdoStuff маршрут? Является ли это теоретически правильным подходом к загрузке модулей и ресурсов RequireJS по требованию? Оптимизатор r.js по-прежнему работает так, как рекламируется, если вы используете эту нотацию?

Ваш Ответ

2   ответа
3

Требуют-ленивым.

Он имеет компонент времени выполнения и компонент времени сборки. Компонент времени выполнения позволяет лениво требовать модуль как (обратите внимание наlazy! плагин):

define(["lazy!mymodule"], function(mymodule) {
    ...
});

В предыдущем контекстеmymodule это Обещание, настоящий модуль будет загружен сget() и будет доступен вthen() Перезвоните

mymodule.get().then(function(m) {
    // here m is the real mymodule
});

Require-lazy интегрируется с r.js для автоматического создания «связок» файлов Javascript. Он также обрабатывает автоматическую очистку кеша для пакетов. Есть несколько примеров, чтобы понять. Существует также Grunt а такжеБеседк интеграция.

50

Это действительно возможно? Есть ли в RequireJS черные магии, которые ищут вызовы require () без фактического запуска маршрута doStuff?

Когда вы используете синтаксис «сахара»оно используетFunction.prototype.toString и регулярное выражение чтобы извлечь ваши ссылки наrequire и затем перечисляет их как зависимости перед запуском функции. В основном это становится обычным стилем определения с массивом deps в качестве первого аргумента.

Из-за этого не имеет значения, где находятся ваши требуемые вызовы, и поэтому условные операторы игнорируются (также объясняется, почему этиrequire вызовы должны использовать строковый литерал, а не переменную).

Является ли это теоретически правильным подходом к загрузке модулей и ресурсов RequireJS по требованию?

Использование синтаксиса сахара не разрешит условную загрузку, как вы видели. Единственный способ, который я могу придумать, это использоватьrequire вызов с массивом deps и обратным вызовом:

define(function(require) {
    var module1 = require('module1');

    // This will only load if the condition is true
    if (true) {
        require(['module2'], function(module2) {

        });
    }

    return {};
});

Единственным недостатком является еще одна вложенная функция, но если вы после исполнения, то это правильный маршрут.

Оптимизатор 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 не требует больших затрат.

Похожие вопросы