Можно ли использовать requirejs, когда необходимо удалить модули для сохранения памяти

Мы разрабатываем приложение во встроенной среде. Это высокоуровневая вычислительная среда с полным веб-браузером поверх загруженной Linux-системы. Единственное исключение состоит в том, что система имеет ограниченное количество системной памяти.

Наше приложение построено в JavaScript и работает внутри веб-браузера на основе Webkit и состоит из множества модулей javascript, которые загружаются последовательно (что не очень эффективно).

Некоторые модули предоставляют общие функции, которые используются несколькими модулями. Мы находимся в процессе преобразования нашего текущего загрузчика javascript с помощью requirejs, но есть одна конкретная необходимость, которую мы должны решить в первую очередь.

Можно ли выгрузить модуль, когда он был загружен с помощью requirejs? Предположим, что мы динамически загружаем модуль, используя:

require(["somemodule.js"], function(m) { m.run(); } );

Это хорошо работает для загрузки и запуска "somemodule" , а также для разрешения всех зависимостей для "somemodule" , а структура requirejs будет хранить ссылку на "somemodule" для будущих запросов.

Если в какой-то момент нам нужно восстановить память, например, чтобы иметь возможность загружать и запускать бесконечное количество модулей, мы должны немного удалить некоторые из них. Возможно ли это с requirejs без изменения внутренней реализации?

Кто-нибудь раньше сталкивался с подобной проблемой? Большинство одностраничных приложений JS работают в веб-браузере на настольном ПК, где использование памяти обычно не является серьезной проблемой.

Ответы

Ответ 1

RequireJS не имеет встроенной функции выгрузки, но ее можно добавить, возможно, в качестве дополнительной части, которую вы могли бы встроить в нее. Если вы хотите использовать эту функцию, не стесняйтесь предлагать ее в списке рассылки или как Проблема GitHub.

Если вы хотите поэкспериментировать, чтобы убедиться, что это помогает вашей ситуации, вам нужно сделать следующее:

1) Удалите указанный модуль из кеша модуля RequireJS. Если вы не используете поддержку мультиверсии, вы можете сделать что-то вроде:

var context = require.s.contexts['_'];
delete context.defined[moduleName];
delete context.specified[moduleName];
delete context.loaded[moduleName];

2) Затем вы можете попробовать удалить тег script, чтобы узнать, помогает ли это:

var scripts = document.getElementsByTagName('script');
for (var i = scripts.length - 1; i >= 0; i--) {
    var script = scripts[i];
    if (script.getAttribute('data-requiremodule') === moduleName) {
        script.parentNode.removeChild(script);
        break;
    }
}

Обратите внимание, что модуль не может быть собран в мусор, если другой модуль удерживает его через функцию закрытия() {}, которая определяет этот другой модуль. Этот другой модуль также нужно будет удалить.

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

Кроме того, в вашем примере выше для модулей, которые используют require.def для определения себя, он должен выглядеть так (без .js-суффикса):

require(["somemodule"], function(m) { m.run(); } );