Lazy загрузки модулей AngularJS с RequireJS
Благодаря большой статье от Dan Wahlin мне удалось реализовать ленивую загрузку контроллеров и служб Angular. Тем не менее, похоже, нет чистого пути к ленивым независимым от нагрузки модулям.
Чтобы лучше объяснить мой вопрос, предположим, что у меня приложение будет структурой, как показано ниже, без RequireJS:
// Create independent module 'dataServices' module with 'Pictures' object
angular.module("dataServices", []).factory("Pictures", function (...) {...});
// Create 'webapp' ng-app, with dependency to 'dataServices', defining controllers
angular.module("webapp", ['dataServices'])
.controller("View1Controller", function (...) {...})
.controller("View2Controller", function (...) {...});
Вот пример приложения с RequireJS в Plunker:
http://plnkr.co/aiarzVpMJchYPjFRrkwn
Ядро проблемы заключается в том, что Angular не позволяет добавлять зависимость к ng-app
после создания экземпляра. В результате мое решение заключается в использовании angular.injector
для извлечения экземпляра объекта Picture
, который будет использоваться в моем View2Controller
. См. js/scripts/controllers/ctrl2.js
файл.
Это создает для меня 2 проблемы:
- Введенные службы выполняются за пределами Angular, и поэтому весь асинхронный вызов должен заканчиваться на $scope. $apply()
- Мессиальный код, в котором некоторый объект может быть введен с использованием стандартного синтаксиса Angular, в то время как другие требуют явного использования инжектора.
Кто-нибудь из вас понял, как ленивый независимый от нагрузки модуль с использованием RequireJS и каким-то образом подключить этот модуль к Angular, чтобы можно было использовать обычный синтаксис зависимостей Angular?
Примечание:
Речь идет о ленивой загрузке независимого модуля. Одним из простых решений для этого конкретного примера является создание объекта "Картинки" с использованием кэшированных поставщиков $во время ng-app.config
, но это не то, что я ищу. Я ищу решение, которое работает с сторонним модулем, например angular-resource
.
Ответы
Ответ 1
Взгляните на мой проект в GitHub: angular-require-lazy
Этот проект призван продемонстрировать идею и мотивировать дискуссии. Но делает то, что вы хотите (проверьте cost-view.js, он загружает ng-сетку лениво).
Меня очень интересуют комментарии, идеи и т.д.
(EDIT) Модуль ng-grid Angular загружается следующим образом:
-
expenses-view.js
загружается лениво, когда активирован маршрут /expenses
-
expenses-view.js
определяет ng-сетку как зависимость, поэтому RequireJs сначала загружает ng-grid
- ng-grid - это тот, который вызывает
angular.module(...)
Чтобы выполнить это, я заменил (фактически прокси) реальный метод angular.module
своим, поддерживающим лень. См. bootstrap.js и route-config.js ( функции initLazyModules()
и callRunBlocks()
).
Эта реализация имеет свои недостатки, о которых вам следует знать:
- Функции конфигурации не реализованы (пока). Я не знаю, можно ли лениво предоставить зависимости времени конфигурации.
- Порядок вопросов в определениях. Если служба A зависит от B, но A определяется после B в вашем модуле, DI wil терпит неудачу. Это связано с тем, что lazyAngular proxy выполняет определения немедленно, в отличие от реального Angular, который гарантирует, что зависимости будут разрешены до выполнения определений.
Ответ 2
Я завершил свою собственную реализацию под названием angularAMD
, и вот пример сайта, который ее использует:
http://marcoslin.github.io/angularAMD/
Он обрабатывает конфигурационные функции и определяет определения модулей порядка.
Надеюсь, это поможет другим людям найти что-то, что поможет им с интеграцией RequireJS и AngularJS.
Ответ 3
Похоже, что Node.js модуль ocLazyLoad
определяет способ выполнения этой ленивой загрузки, хотя я не уверен, как это оценивается по производительности, по сравнению с методами в других ответах или жестко кодировать зависимости. Любая информация об этом будет оценена по достоинству. Интересно, что для других ответов требуется RequireJS
, а ocLazyLoad
- нет.
Похоже, что ocLazyLoad
определяет другого провайдера, который вводит зависимость после того, как содержащийся модуль уже был создан. Это, по-видимому, делает это, по существу, дублируя поведение низкоуровневого Angular, например загрузку и предоставление модулей, поэтому он выглядит настолько сложным. Похоже, что он добавляет почти каждый ядро Angular в качестве зависимости: $compileProvider
, $q
, $injector
, ng
и т.д.