web-dev-qa-db-fra.com

Chargement paresseux des modules AngularJS avec RequireJS

Grâce au grand article de Dan Wahlin , j'ai réussi à implémenter le chargement paresseux des contrôleurs et services d'Angular. Cependant, il ne semble pas y avoir de méthode propre pour charger des modules indépendants paresseux.

Pour mieux expliquer ma question, supposons que j'ai une application qui serait structurée comme ci-dessous sans 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 (...) {...});

Voici l'exemple d'application avec RequireJS dans Plunker:
http://plnkr.co/aiarzVpMJchYPjFRrkwn

Le cœur du problème est que Angular ne permet pas d'ajouter des dépendances à ng-app après instanciation. Par conséquent, ma solution consiste à utiliser angular.injector pour récupérer l'instance de Picture objet à utiliser dans mon View2Controller. Voir js/scripts/controllers/ctrl2.js fichier.

Cela crée 2 problèmes pour moi:

  1. Les services injectés s'exécutent en dehors de angular et donc tous les appels asynchrones doivent se terminer par $ scope. $ Apply ()
  2. Code désordonné où certains objets peuvent être injectés en utilisant la syntaxe standard angular tandis que d'autres nécessitent l'utilisation explicite de l'injecteur.

Avez-vous pensé à charger paresseusement un module indépendant à l'aide de RequireJS et à raccorder ce module en quelque sorte angular si normal angular la syntaxe d'injection de dépendance peut être utilisée?)

Remarque :
La question porte sur le chargement paresseux de module indépendant. Une solution simple à cet exemple spécifique consiste à créer un objet "Images" à l'aide des fournisseurs $ mis en cache pendant ng-app.config mais ce n'est pas ce que je recherche. Je recherche une solution qui fonctionne avec un module tiers tel que angular-resource.

22
marcoseu

Jetez un oeil à mon projet dans GitHub: angular-require-lazy

Ce projet vise à démontrer une idée et à motiver les discussions. Mais est fait ce que vous voulez (vérifiez dépenses-vue.js , il charge ng-grid paresseusement).

Je suis très intéressé par les commentaires, les idées, etc.


(EDIT) Le module ng-grid Angular module est chargé paresseusement comme suit:

  1. expenses-view.js Est chargé paresseusement, lorsque la route /expenses Est activée
  2. expenses-view.js Spécifie ng-grid comme une dépendance, donc RequireJs charge ng-grid en premier
  3. ng-grid est celui qui appelle angular.module(...)

Pour ce faire, j'ai remplacé (en fait un proxy) la vraie méthode angular.module Par la mienne, qui prend en charge la paresse. Voir bootstrap.js et route-config.js (les fonctions initLazyModules() et callRunBlocks()).

Cette implémentation a ses inconvénients que vous devez savoir:

  1. Les fonctions de configuration ne sont pas (encore) implémentées. Je ne sais pas s'il est possible de paresseusement fournir config-time dépendances.
  2. Ordonner les questions dans les définitions. Si le service A dépend de B mais que A est défini après B dans votre module, DI échouera. En effet, le proxy lazyAngular exécute les définitions immédiatement, contrairement à la vraie Angular qui s'assure que les dépendances sont résolues avant d'exécuter les définitions.
10

J'ai finalisé ma propre implémentation appelée angularAMD et voici l'exemple de site qui l'utilise:

http://marcoslin.github.io/angularAMD/

Il gère les fonctions de configuration et les définitions de modules en panne.

J'espère que cela peut aider les autres à chercher quelque chose pour les aider avec l'intégration de RequireJS et AngularJS.

17
marcoseu

Il ressemble au module Node.js ocLazyLoad définit une façon de faire ce chargement différé, mais je ne sais pas comment cela se passe, en termes de performances, par rapport aux méthodes de les autres réponses ou coder en dur les dépendances. Toute information à ce sujet serait appréciée. Une chose intéressante est que les autres réponses ont besoin de RequireJS pour fonctionner, tandis que ocLazyLoad ne fonctionne pas.

Il semble que ocLazyLoad définit un autre fournisseur qui injecte la dépendance après que le module conteneur a déjà été instancié. Il semble faire cela en répliquant essentiellement certains comportements de bas niveau Angular, comme le chargement et la fourniture de modules, d'où la raison pour laquelle cela semble si compliqué. Il semble qu'il ajoute à peu près tous les cœurs Angular en tant que dépendance: $compileProvider, $q, $injector, ng, et bien d'autres.

1
trysis