Angular: NgModule sur les grands projets

Créé le 7 août 2016  ·  144Commentaires  ·  Source: angular/angular

Je soumets un ... (cochez-en un avec "x")

[X] feature request / proposal

J'ai lu des articles sur NgModule et je souhaite présenter quelques cas d'utilisation que je ne suis pas tout à fait sûr que la proposition actuelle (https://docs.google.com/document/d/1isijHlib4fnukj-UxX5X1eWdUar6UkiGKPDFlOuNy1U/pub) prend en considération .

Le contexte

Je fais partie d'une équipe qui construit un Enterprise Framework (basé sur Angular 2). Ce cadre servira ensuite de base à d'autres applications au sein du même écosystème.

Nous avons divisé le cadre en projets/modules plus petits (considérez-les comme des packages npm séparés). Ces modules sont des ensembles de contrôles (qui sont ensuite réutilisés dans d'autres modules) ou des pages qui utilisent ces contrôles.

Exemple

Un exemple rapide peut être :

Module de contrôle

import {Component} from "@angular/core";

@Component({
   selector: "my-combobox",
   ...
})
export class MyComboBox{

}

Module de liste de contrôle
// Le module Checklist dépend du module Controls. Les contrôles sont traités comme un module tiers.

import {Component} from "@angular/core";
import {MyComboBox} from "controlsmodule/components/mycombobox";
// Please note that we are only loading a specific component within the module, not all components inside that module.

@Component({
     selector: "my-checklist-page",
     directives: [MyComboBox, ...],
     ...
})
export class ChecklistPage{

}

Bootstrap ne connaît pas les modules Controls et Checklist. Ils sont chargés paresseux en fonction de l'interaction de l'utilisateur. Dans ce cas, si l'utilisateur navigue vers une Checklist, le composant ChecklistPage sera chargé puis la MyComboBox suivra également (à cause de l'_import_ effectué par ChecklistPage)

Le module de liste de contrôle comporte une douzaine d'autres composants. Chacun dépendant d'une douzaine d'autres composants de plusieurs modules.

Il n'est pas pratique (pour ne pas dire presque impossible) d'avoir tous les composants importés dans la déclaration NgModule. Nous parlons de plusieurs centaines de composants qui _pourraient_ être utilisés pendant l'exécution de l'application.

De plus, l'application doit être modulaire et lazy load lorsque cela est possible. Différentes interactions au sein de l'application entraîneront le chargement de modules complètement différents.

Comportement attendu/souhaité

La solution actuelle, avec des directives de portée de composant, fonctionne comme un charme pour ce cas d'utilisation. Je ne sais pas comment cela se passera avec NgModule.

Plus que cela, nous pouvons actuellement voir clairement les dépendances nécessaires à chaque composant (dans ce cas, ChecklistPage). Rendre l'entretien beaucoup plus facile.

Avoir tous les composants nécessaires importés dans un NgModule, puis les utiliser indistinctement sur plusieurs composants semble une solution fantastique pour les petites applications. Je pense que sur un développement à long terme, avec plusieurs itérations sur plusieurs années, avec rotation d'équipe, ... avoir chaque composant énonçant explicitement ce dont il dépend sans regarder dans le modèle (et avoir des erreurs de compilation quand quelque chose manque) est un grand avantage.

Conclusion

Merci de me dire si j'ai été clair dans mon explication. L'objectif de ce numéro est de sensibiliser à cette situation et d'obtenir des commentaires de votre part sur la marche à suivre.

Nous sommes disponibles pour vous montrer notre travail en cours, nous avons plusieurs centaines de composants Angular 2 à travers 8 projets développés l'année dernière (depuis l'alpha 27).

Commentaire le plus utile

Merci pour les commentaires à tous, excuses, il a fallu si longtemps pour obtenir une réponse - nous avons été très occupés la semaine dernière (migration des applications Google internes vers NgModules, nous ressentons donc également la douleur de la refactorisation)

Permettez-moi de voir si je peux éclaircir certaines des questions et des idées fausses ici.

La première chose à comprendre à propos de @NgModule() (et de @Component et de tout autre décorateur Angukar) est qu'ils sont purement construits au moment de la compilation - ils existent pour permettre au compilateur angulaire de découvrir un graphe de dépendance dans une application.

Une version (simplifiée) de ce que font nos décorateurs ressemble à :

//simplified Component decorator
export function Component(componentConfig){
  return function(componentClass){
    Reflect.defineMetadata('annotations', componentConfig, componentClass);
  }
}

Ils ne changent ni ne modifient en aucune façon le comportement de la classe décorée - ils attachent simplement des métadonnées. Angular utilise ces métadonnées pour construire votre application et compiler des modèles.

En mode JiT, cela se produit "juste à temps" - entre l'appel de bootstrapModule et le rendu de votre premier composant, le compilateur d'Angular récupère les métadonnées attachées aux classes à l'aide de l'API Reflect :

let metadata = Reflect.getOwnMetadata('annotations', componentClass);

En mode AoT cependant, cela fonctionne un peu différemment - au moment de la construction, nous extrayons _statiquement_ (c'est-à-dire sans exécuter votre code) les mêmes métadonnées du code source en recherchant des décorateurs.

Cela fonctionne bien lorsque vous démarrez un seul composant, mais nous avons entendu beaucoup de commentaires de développeurs qui font des choses plus complexes - démarrage de plusieurs composants racine, ou démarrage de différents composants en fonction du statut d'authentification, etc.

Ainsi, alors que les décorateurs @Component nous donnaient la possibilité d'analyser statiquement un composant, nous n'avions pas la possibilité d'analyser statiquement de manière fiable une _Application_

Choses qui relèvent d'une "application"

  • PLATFORM_DIRECTIFS/TUYAUX/FOURNISSEURS
  • choses que vous avez précédemment ajoutées à bootstrap()
  • paramètres au niveau du compilateur
  • plusieurs composants racine
  • utilisation côté serveur.

Les NgModules introduisent l'idée d'un ensemble de fonctionnalités analysables statiquement. Ce qui est intéressant, c'est qu'en mode compilation AoT, nous analysons votre module racine et _générons_ une ModuleFactory pour chaque module de l'application - il s'agit de la version pré-compilée d'un module, qui contient _uniquement_ les fabriques que vous référencez statiquement dans les modèles et celles que vous marquer comme "entryComponents"

Parce que nous avons déjà extrait les informations nécessaires à la compilation à l'avance, nous pouvons en fait secouer les décorateurs (ngc s'en chargera automatiquement pour la version finale) - et plutôt que de regrouper votre application en commençant par votre module racine, vous démarrez à votre racine générée Module_Factory_, qui ne contient que le code réellement utilisé dans votre application, vous ne payez donc pas de pénalité pour la modularité, et des outils comme rollup et webpack2 peuvent fonctionner _plus_ efficacement

plus à suivre dans la prochaine réponse...

Tous les 144 commentaires

Il ne me semble pas que ngModules interdise la configuration que vous recherchez, avez-vous déjà joué avec ? Vous pouvez avoir plusieurs modules différents et effectuer un chargement paresseux, etc. http://plnkr.co/edit/NAtRQJBy50R19QAl90jg?p=info

Pour quelque chose de plus similaire à ce que vous semblez essayer de faire, gardez un œil sur la transition de material2 : https://github.com/angular/material2/pull/950/files

Salut @qdouble ,

Merci pour la réponse rapide.
En regardant https://github.com/jelbourn/material2/blob/ecbb4f42e0473899f6ad15d8e4ed8f262ded7a99/src/components/button-toggle/button-toggle.ts , dites-vous que pour obtenir la même fonctionnalité que nous avons maintenant, nous avons besoin déclarer un NgModule sur chaque composant ? (c'est ce qui a été ajouté à la fin du fichier, n'est-ce pas ?)

De plus, cela ne couvre pas le problème de maintenance que j'ai mentionné dans ma déclaration initiale. Avoir les dépendances de chaque composant/directive déclarées sur son décorateur est, pour moi, un grand avantage que j'aimerais garder.

@jpsfs si vous vouliez créer une portée individuelle pour chaque composant, alors je suppose que vous devriez créer différents ngModules pour chacun. Bien que cela puisse créer plus de code dans votre cas, je suppose que cela créera moins de code pour la grande majorité des autres personnes en délimitant mon module plutôt que par composant.

En ce qui concerne le deuxième problème, vous pouvez déclarer le ngModule et le composant juste à côté l'un de l'autre, donc même si cela ajouterait 3 ou 4 lignes de code supplémentaires à vos fichiers, je ne pense pas que cela crée un énorme problème.

Je dirais que la grande majorité des cas d'utilisation ne nécessitent pas de directives étendues par composant, mais dans le cas où c'est le cas, ngModules le prend toujours en charge pour quelques lignes de code supplémentaires.

@qdouble Merci.

Je ne suis pas sûr que ce soit une situation ou/ou, je peux voir les deux scénarios fonctionner ensemble, pas besoin de supprimer la fonctionnalité que nous avons déjà. Si quelqu'un veut utiliser des modules, je peux voir cela comme un excellent ajout. Pendant ce temps, le framework pourrait fonctionner sans modules (comme il fonctionne aujourd'hui). Je crois que même le problème de compilation hors ligne peut être résolu avec les choses telles qu'elles sont actuellement.

Je laisse cela ouvert pour voir si quelqu'un a quelque chose à ajouter à la question.

@jpsfs compris, si j'étais dans votre situation, je préférerais certainement qu'ils laissent les deux options ouvertes :)

Ils ont écrit la raison de la dépréciation des directives de composant dans la documentation que vous avez publiée, en ce qui concerne la création de deux portées, pensant que la portée de ngModule est suffisamment petite et qu'elle est plus conforme au modèle ES6.

Un membre de l'équipe a également mentionné auparavant qu'il est généralement problématique d'avoir deux façons différentes de faire les choses... et à long terme, je pourrais voir le problème ici... si vous avez des projets où les gens utilisent ngModules et d'autres projets là où il n'y en a pas, cela crée plus de problèmes de maintenance, de formation et de compatibilité.

On ne sait jamais dans quelle direction ce projet ira jusqu'à ce qu'il soit finalisé, donc nous verrons s'ils prennent en considération ce que vous dites.

Même moi, je travaille actuellement sur la conception de l'architecture d'une énorme application d'entreprise.
Contrairement à votre situation @jpsfs , je suis enthousiasmé par NgModules et j'ai à peu près basé l'architecture de mon application autour de NgModule.

Chaque module aura son propre ensemble de routes et de dépendances de composants. Nous ne pouvons jamais créer une fonctionnalité avec un seul composant, elle a besoin de routes, d'au moins un composant intelligent et de quelques composants et services stupides pour l'accompagner. Branchez tout cela dans un module et vous êtes prêt à partir.

En ce qui concerne le chargement paresseux, au lieu de charger du code pour chaque composant, il semble bon que chaque code NgModule soit chargé en même temps, de sorte que votre fonctionnalité soit pleinement utilisable une fois téléchargée.

La création d'une hiérarchie de modules est également beaucoup plus simple et offre une excellente fonctionnalité Plug and Play gratuitement.

Nous travaillons également actuellement sur une application avec pas mal de composants (pas des centaines mais des dizaines). Il n'y a aucun besoin architectural pour nous de diviser cette application en plusieurs modules (chargés paresseux), mais maintenant importer tous ces composants dans le fichier d'amorçage et les transmettre à declarations semble en quelque sorte faux et casse l'encapsulation du composant . Comme @jpsfs l' a dit, auparavant, il était très clair quels composants et directives étaient utilisés par un autre composant. Donc j'apprécierais aussi d'avoir le choix :

  • S'il s'agit d'une directive assez couramment utilisée, déclarez-la dans le module
  • Si c'est quelque chose comme TaskListItem , importez-le simplement dans TaskList .

Peut-être qu'un membre principal peut en dire plus sur la décision de déprécier la deuxième approche. Ayant travaillé avec depuis plusieurs mois maintenant, ça fait du bien ;)

Pour faire écho au point de @choeller , il est étrange de s'éloigner de la capacité de fournir l'encapsulation des composants.

Ma préoccupation spécifique est que maintenant les noms/sélecteurs de composants fuient dans toute l'application, alors qu'auparavant, vous pouviez réutiliser des sélecteurs pour différents composants en incluant des directives spécifiques, le cas échéant.

Maintenant, tous les sélecteurs devraient être uniques par composant, n'est-ce pas ? Ou est-ce que je comprends mal comment cela fonctionne?

J'ai estimé que la fonctionnalité d'origine correspondait aux avantages similaires fournis par l'émulation CSS shadow-DOM, en ce sens que nous pouvions moins nous soucier des collisions de sélecteurs, etc. dans les grandes applications. C'était un grand avantage IMO.

Ma première pensée à propos de ngModule a été "Oh, c'est comme dans angular 1". Aussi génial que l'Angular 1 l'était déjà, l'Angular 2 est tellement meilleur à bien des égards. Le meilleur point pour moi était que les composants créent une sorte d'arbre de dépendance. J'ai un composant principal avec un routeur qui définit plusieurs points d'entrée avec son propre composant. Et chaque composant sait ce dont il a besoin, aucune raison pour que le composant principal sache ce dont l'un des composants à la fin de l'arborescence a besoin.
Nous sommes maintenant de retour au bon vieux temps d'angular 1, où nous avons une définition de module géante.
Vous souvenez-vous des moments où votre point d'entrée d'application ressemblait à ceci ?

angular.module("myApp")
.controller("…")
.controller("…")
.controller("…")
.controller("…")
.controller("…")
.controller("…")
.component("…")
.component("…")
.component("…")
.component("…")
.component("…")
.component("…")
.directive("…")
.directive("…")
.directive("…")
.directive("…")
.directive("…")
.directive("…")
.directive("…")
.service("…")
.service("…")
.service("…")
.service("…")
.service("…")
.service("…")

Je pensais que cela appartenait au passé. J'ai commencé à travailler avec ng-metadata pour améliorer les anciens projets angular 1 et préparer la migration. J'aime vraiment le fait qu'il ait un arbre de dépendances et non une liste globale "ce qui pourrait apparaître dans cette application".

Cela rend les composants réutilisables plus difficiles. Je ne comprends pas comment cela améliore les choses en ayant tout dans une portée globale/module, je pense que l'équipe ng2 a cédé aux utilisateurs ng1 qui ne veulent pas de changement.

@DaSchTour @damiandennis Je comprends la critique de cette architecture, cependant, en y faisant référence comme une sorte de portée globale est inexacte, la méthodologie qu'ils vous suggèrent de prendre est d'avoir des modules de fonctionnalités : https://angular.io/docs/ts /dernier/guide/ngmodule.html# ! #feature-modules

@qdouble Eh bien, au final, il ne s'agit que de changer tous les composants en modules. Bien que cela soit annoncé comme un changement pour réduire le code passe-partout, il introduit un grand nombre de besoins passe-partout.

Alors que jusqu'à RC4 un composant pour chaque "page"/vue de l'application suffisait, sachez que je devrai créer un module, un composant et un routage pour chaque vue. Je reçois l'intention. Mais j'ai en quelque sorte l'impression qu'il est conçu pour faciliter certaines choses sans concerner beaucoup d'autres points. Et même avec le modèle de module de fonctionnalité, je dois les couper très petits pour éviter l'enfer des dépendances, en ajoutant tout ce qui pourrait être nécessaire car je ne vois pas quelle partie de mon application a besoin de quels composants.

En fin de compte, les modules sont si petits qu'ils ont les mêmes listes de dépendances répétitives que les composants actuels.

En fin de compte, cela ne résout pas ce pour quoi il a été conçu et ne fait qu'ajouter beaucoup de travail. J'ai l'impression qu'il y a un décalage entre le design et la réalité ici.

les développeurs sont paresseux/à court de temps et prennent des raccourcis. Cela encourage les développeurs à emprunter la voie rapide consistant à tout inclure dans bootstrap. Au moins avec les composants, il est nécessaire d'inclure vos dépendances. Oui, ils peuvent également être paresseux et créer un seul composant pour l'ensemble de l'application, mais ce serait plus facile à corriger car les dépendances sont toutes dans ce composant et non mélangées entre le fichier d'amorçage et chaque fichier de composant de l'application.

@DaSchTour si chaque composant a besoin de sa propre portée, alors oui, cela créera plus de passe-partout ... mais je suppose que l'équipe ng est d'avis que pour la plupart des gens, créer un nouveau module pour chaque section de fonctionnalités est suffisant et quelques composants pourraient vivre dans chaque espace de fonctionnalité.

Maintenant, évidemment, il n'y a pas de solution unique et avoir des directives au niveau des composants peut être plus simple pour certaines personnes. Cependant, il semble que beaucoup de commentaires ici impliquent qu'ils veulent que vous créiez simplement une application avec un énorme arbre ngModule ...

Je pense que c'est plus productif si la critique est basée sur leurs suggestions de conception réelles plutôt que sur un modèle de conception d'homme de paille qu'ils ne suggèrent pas (c'est-à-dire créer une application d'entreprise qui n'est qu'un énorme ngModule)

@qdouble le modèle de conception est simple. Il utilise une arborescence de dépendances au lieu de déplacer les dépendances vers une étendue de module globale. Je suppose que le point principal est que les composants réutilisables doivent maintenant être des modules, même s'ils sont très petits et n'ont que très peu de fonctionnalités. Le matériau angulaire2 en est un très bon exemple. Un bouton est un module, comprenant un composant. C'est peut-être une idée fausse générale de nombreux développeurs, qu'un module est quelque chose qui contient plus qu'un simple bouton. Et maintenant, réfléchissons un peu plus loin. En suivant simplement les idées de cet article https://angularjs.blogspot.com/2016/08/angular-2-rc5-ngmodules-lazy-loading.html je me trouve au point, que j'ai beaucoup de modules qui importer une liste de modules angular material2 et chacun de ces modules constitué d'un seul composant.
En fait, c'est exactement ce que fait angular material2.

Personne ne comprend vraiment pourquoi nous devons maintenant encapsuler "tous" nos composants dans des modules. Ou peut-être devons-nous voir cela comme une scission de la déclaration. Les dépendances des composants sont maintenant un module et la définition des composants est telle qu'elle était.

Je suppose que le fait est que les ngModules ne sont pas seulement un bel ajout pour faciliter les choses, mais nous sommes obligés de tout changer. Peut-être que quelqu'un devrait expliquer clairement pourquoi les deux ne peuvent pas coexister.

@DaSchTour eh bien oui, je suis d'accord que si chaque composant que vous créez a besoin de son propre module, alors l'utilisation de ngModules crée plus de passe-partout ... Je suppose simplement que l'équipe ne pense pas que la plupart des gens auront besoin de ce niveau de séparation pour chaque composant.

Je me trouve au point où j'ai beaucoup de modules qui importent une liste de modules angulaires de material2 et chacun de ces modules est constitué d'un seul composant.

Vous utiliserez des modules partagés pour cela : https://angular.io/docs/ts/latest/guide/ngmodule.html# ! #module-partagé

Maintenant, je ne sais pas vraiment non plus pourquoi ils pensent qu'il est nécessaire de supprimer totalement la possibilité d'avoir une portée de composant, mais pour moi, certaines des critiques rendent l'utilisation de ngModules plus difficile qu'elle ne l'est réellement ou rendent la conception semble plus bâclé qu'il ne l'est en réalité.

Je pense que la critique de la suppression des directives/tuyaux de portée des composants est parfaitement valable. Cependant, je ne pense pas qu'il soit nécessaire de donner l'impression qu'il n'y a pas de bons modèles de conception pour ngModules.

@qdouble Je pense que personne ne doute qu'il existe de bons modèles de conception pour ngModules. Mais d'après ce que je comprends, les modules ne sont qu'un emballage autour d'un ensemble de composants, de directives et de services pour les exposer comme une unité à l'application. C'est valable et une excellente idée. Mais pourquoi dois-je définir les dépendances (qui ne peuvent exister qu'à l'intérieur du module) pour le module et non pour le composant.

Prenant l'exemple de @choeller
Le module TaskDashboard a les choses suivantes

  1. Composant de la liste des tâches
  2. Composant de l'élément de tâche
  3. Composant de filtre de tâches
  4. Service de tâches

Le composant Taskitem n'est nécessaire qu'à l'intérieur de la liste des tâches et la liste des tâches dépend du composant Taskitem. Le filtre de tâches n'a pas besoin du composant Taskitem. Maintenant, je n'ai pas le Taskitem comme dépendance dans la liste des tâches. La prochaine étape consiste à créer un module TaskSearch. J'ajoute les éléments suivants.

  1. Composant de la liste des tâches
  2. Composant de recherche de tâches
  3. Service de tâches

Eh bien, j'ai raté le composant Taskitem et il est cassé. La liste des tâches dépend toujours de Taskitem, mais cette dépendance est masquée dans le module. La réutilisation des composants est rendue plus difficile et crée une source supplémentaire d'erreurs.

D'accord, en lisant davantage le guide des modules, j'ai trouvé cette ligne

Les composants, les directives et les pipes doivent appartenir à exactement un module.

Donc, l'exemple montre exactement la préoccupation qui est soulevée ici. Il ne peut y avoir aucun composant partagé. Donc, à partir de mon exemple, je devrais tout diviser en modules.

En travaillant sur les erreurs étranges et non insaisissables qui surviennent lors de l'utilisation de ngModule, j'ai également découvert que l'extension des composants ne fonctionnait plus aussi bien qu'avant. J'avais un ensemble de composants avec les dépendances nécessaires que je pouvais simplement étendre. Maintenant, je dois m'occuper d'importer les dépendances dans le module dans lequel j'inclus mon composant étendu.

@DaSchTour dans votre exemple, Taskitem devrait faire partie du module Tasklist ... donc ce serait logiquement deux composants dans un module, pas un pour chacun.

Comme @sirajc l' a souligné, un modèle de conception typique serait d'avoir un composant intelligent supérieur, suivi de composants muets supplémentaires... donc dans une application typique du monde réel, la plupart des modules seraient constitués de quelques composants (que ce soit par le composant intelligent/muet modèle de composant ou par modèle de fonctionnalité connexe), pas seulement un composant par module, sauf si vous construisez simplement des composants tiers ou quelque chose du genre.

@qdouble @DaSchTour Il est vrai que la nouvelle architecture ne signifie pas nécessairement que vous répertoriez tous vos composants dans un seul fichier, mais en regardant l'application que nous construisons, j'irais actuellement à peu près avec cette déclaration de @DaSchTour

J'ai l'impression qu'il y a un décalage entre le design et la réalité ici.

Nous avons donc un certain nombre de composants représentant de petites unités sur la page comme TaskListItem qui sont liés à 100 % à une vue spéciale. Créer des modules pour chacune de ces pages serait une exagération totale. Dans notre cas, il y a très peu de raisons de se diviser en plusieurs modules, mais bien plus de raisons d'encapsuler des composants.

tl;dr
C'est cool de pouvoir définir certaines dépendances au niveau du module, mais c'est vraiment dommage que nous ne soyons plus en mesure de définir des dépendances au niveau du composant

@DaSchTour , dans le composant de bouton material2 est lié au module pour le rendre autonome. Ceux qui ont besoin d'utiliser le bouton peuvent importer ButtonsModule . De plus, si vous voyez le code du module, il contient deux composants MdButton et MdAnchor , l'emballage puis dans ButtonsModule rend les choses plus faciles à utiliser

Je me demande s'il est possible de créer un objet composant/module hybride qui fusionne les deux concepts en un seul pour éviter la duplication des fichiers. Essentiellement, être capable de déclarer un composant en tant que module une fois, puis de l'importer en tant que module, si nécessaire. Cela respecterait l'approche actuelle, mais minimiserait le passe-partout.

@choeller Je suis d'accord que le fait d'avoir des modules est un bon ajout, mais supprimer les dépendances au niveau des composants semble tout simplement faux.

En s'appuyant sur ce que d'autres ont écrit ci-dessus, je pense que l'idée centrale ici n'est pas de vivre la misère d'un énorme projet avec un énorme module contenant des centaines de composants. Il s'agit plutôt de créer une application à partir d'un nombre raisonnable de NgModules de taille moyenne. Assez gros pour qu'ils ne soient pas triviaux, assez petits pour qu'il n'y en ait pas un grand nombre ; divisé le long de lignes de faille qui tendraient à faciliter la réutilisation et la modularité dans le sens informatique à l'ancienne de haute cohésion et de faible couplage.

Ce faisant, les modules devraient s'avérer être un concept assez utile pour les faire jouer sur de grands projets.

C'est très bien résumé @kylecordes. NgModules aide à la composition agréable de l'application. Les petits modules réutilisables constituent toute l'application.
L'autre avantage inclut la disponibilité ambiante des directives. Auparavant, nous avions l'habitude d'ajouter ROUTER_DIRECTIVES dans toute l'application. Maintenant, RouterModule.forRoot() fait pour nous.
BrowserModule, CommonModule, FormsModule est plus logique que d'inclure des directives dans chaque composant.

MaterialModule, d'autre part, fournit tout et si vous avez besoin d'un contrôle plus précis, ButtonsModule, etc. nous aidera.
C'est la beauté de la composition. Adoptez-le et créez votre symphonie

En plus de cela, il y a le LazyLoading. Sinon pour NgModules, comment définir le nombre de composants et de services qui doivent aller ensemble pour créer une unité Routable. Vous ne pouvez pas télécharger de fichiers en vrac, car cela entraînera une énorme quantité de requêtes réseau. Sinon, vous devez créer un bundler dans lequel vous répertoriez tous les fichiers dépendants pour créer un bundle. NgModule le fait avec une syntaxe intuitive.

@kylecordes

En s'appuyant sur ce que d'autres ont écrit ci-dessus, je pense que l'idée centrale ici n'est pas de vivre la misère d'un énorme projet avec un énorme module contenant des centaines de composants. Il s'agit plutôt de créer une application à partir d'un nombre raisonnable de NgModules de taille moyenne. Assez gros pour qu'ils ne soient pas triviaux, assez petits pour qu'il n'y en ait pas un grand nombre ; divisé le long de lignes de faille qui tendraient à faciliter la réutilisation et la modularité dans le sens informatique à l'ancienne de haute cohésion et de faible couplage.

Ces lignes de faille ne seraient-elles pas très différentes pour les développeurs d'applications et les développeurs de bibliothèques. Les développeurs de bibliothèques devraient être minoritaires, mais cela semble être le principal reproche. Lors de la construction d'un framework réutilisable, l'objectif de vouloir minimiser la taille du module entraîne beaucoup de bruit supplémentaire.

@sirajc

En plus de cela, il y a le LazyLoading. Sinon pour NgModules, comment définir le nombre de composants et de services qui doivent aller ensemble pour créer une unité Routable. Vous ne pouvez pas télécharger de fichiers en vrac, car cela entraînera une énorme quantité de requêtes réseau. Sinon, vous devez créer un bundler dans lequel vous répertoriez tous les fichiers dépendants pour créer un bundle. NgModule le fait avec une syntaxe intuitive.

J'ai pu le faire facilement avec l'ancien routeur en utilisant simplement un composant qui fonctionnait comme un conteneur pour une section de mon application. Ce module n'apportait que les composants directs dont il avait besoin, ce qui apporterait leurs propres dépendances. Tout chargeur de module décent serait capable de charger la chaîne de dépendance (via des importations) de ce composant sans inclure toutes les sous-dépendances dans le composant de niveau supérieur. Il en va de même pour les bundlers qui doivent utiliser une sorte de logique de résolution de module. En bref : il n'y a aucune raison, du point de vue du chargement paresseux, pour qu'un développeur doive déclarer toutes les dépendances contenues dans le composant de niveau supérieur.

On a vraiment l'impression que ngModule est une solution à la recherche d'un problème...

Il y a quelque chose à dire pour pouvoir ouvrir n'importe quel composant donné, jeter un coup d'œil à son tableau de directives et savoir exactement de quels composants/directives il dépend. Est-il plus verbeux d'avoir à importer un composant de bouton parmi les nombreux composants qui l'utilisent ? Oui, mais je préférerais avoir un passe-partout supplémentaire et que les choses soient explicites et immédiatement scannables plutôt que de rechercher dans l'arborescence des composants/modules pour voir comment le composant Y utilise le composant X dans son modèle sans jamais l'importer.

L'argument avancé ci-dessus est que si quelqu'un souhaite garder les composants isolés les uns des autres, il pourrait sans doute créer un module pour chaque composant - mais à ce stade, vous écrivez encore plus de passe-partout que le composant d'origine n'en avait jamais eu.

Il y a évidemment d'autres avantages à ngModule que je n'ai pas couverts, et bien qu'il y ait des avantages à pouvoir regrouper des sections d'une application dans des modules de fonctionnalités, cela ressemble vraiment à un pas en arrière en matière de clarté et d'avoir des composants encapsulés. code qui ne fuit pas partout.

Une partie de la "vente agressive" que l'équipe ng2 a dû faire à la communauté depuis ng1 était "oui, vous allez devoir importer et déclarer vos directives pour chaque composant, mais faites-nous confiance, vous apprécierez d'être plus explicite au fur et à mesure que votre application grandit". Je crois fermement qu'il faut subir un peu de répétition pour des raisons de lisibilité et de scannabilité dans un environnement d'équipe à grande échelle où un membre de l'équipe ne peut travailler que sur un très petit sous-ensemble de composants à un moment donné.

À tout le moins, je ne vois aucune raison pour laquelle ngModule et la propriété directives/pipes ne peuvent pas coexister. L'alternative est que chaque composant de chaque application écrite pour ng2, jusqu'à RC5, utilise désormais un code obsolète qui doit être refactorisé de manière non triviale. Ce n'est vraiment pas le genre de changements auxquels je m'attendrais si tard dans le développement... c'est assez déconcertant honnêtement.

ngModules nécessite essentiellement une réécriture de la plupart des applications si elles doivent être structurées correctement ... mais la plus grande idée fausse est qu'elles forcent un niveau de portée particulier alors que la réalité est que vos modules peuvent être aussi grands ou aussi petits que vous le souhaitez. être.

Si vous devez absolument créer un nouveau module pour chaque composant, il en résulte plus de passe-partout = valide.

La plupart des applications devraient vous obliger à créer un module pour chaque composant = invalide (surtout si vous utilisez des modèles de composants intelligents/stupides et des modèles de fonctionnalités)

Pour la première fois aujourd'hui, j'ai ressenti la lassitude côté client / JavaScript que plusieurs collègues m'ont transmise. J'ai perdu d'innombrables heures au cours des derniers jours à essayer de refactoriser notre application RC4 pour utiliser les nouveaux modules RC5.

Je suis définitivement d'accord avec un certain nombre de sentiments dans ce fil, en particulier sur le fait de donner aux développeurs le choix de la manière dont ils souhaitent structurer leurs dépendances de composants. Je n'aime pas qu'un ngModule plus grand dilue le graphique de dépendance clair entre les composants et que des ngModules plus petits ajoutent du code passe-partout supplémentaire à chaque composant. Lors de l'analyse d'un module, tout ce que je sais, c'est qu'au moins l'un des composants référencés a besoin d'éléments provenant des importations ou des déclarations de frères du module. Si je sépare un module en plusieurs autres modules, il me reste essentiellement des essais et des erreurs pour déterminer les dépendances dont les nouveaux modules ont besoin (une inspection minutieuse du modèle de composant aide, quelque peu).

Enfin, si j'"oublie" d'exporter des composants, mon composant ne s'affiche tout simplement pas, aucune erreur n'est générée. C'est facile à trouver si vous avez un graphe de module très plat, presque impossible quand vous avez plusieurs niveaux !

À ce stade, je suis découragé, déçu et découragé. J'ai embarqué une équipe de développeurs et d'acteurs commerciaux avec une technologie que je ne sais pas si je peux faire avancer. J'espère vraiment qu'un meilleur équilibre pourra être trouvé.

À ce stade, je suis découragé, déçu et découragé. J'ai embarqué une équipe de développeurs et d'acteurs commerciaux avec une technologie que je ne sais pas si je peux faire avancer. J'espère vraiment qu'un meilleur équilibre pourra être trouvé.

Je suppose que le point ici est qu'il y a un nombre géant de développeurs qui attendent que cette technologie soit prête pour la production et bien qu'elle s'appelle Release Candidate, chaque nouveau candidat apporte des changements de rupture et cela ressemble plus à un alpha.

Je suis sûr que beaucoup d'équipes ont passé des heures sur l'architecture de leurs nouvelles applications et maintenant c'est fou.

Quel sera le prochain breaking change ? Je ne peux même pas imaginer, mais je crains que quelqu'un ne trouve un moyen d'introduire le prochain changement de rupture.

Extrait du billet de blog RC5 :

Si vous avez écrit du code Angular 2, vous vous êtes probablement demandé "mais POURQUOI dois-je lister toutes ces choses !?" - surtout si vous avez remarqué que certaines directives et tuyaux dans Angular 2 sont "spéciaux" - ils sont disponibles pour l'ensemble de votre application sans que vous ne fassiez quoi que ce soit ( *ngFor / *ngIf / *ngSwitch, par exemple).

Personnellement, je n'ai pas vu cette question posée par qui que ce soit depuis un certain temps. Jusqu'à RC5, l'équipe Angular, les ressources d'apprentissage en ligne, les livres, etc. ont tous clairement expliqué pourquoi ces déclarations sont nécessaires - et il semble que tout le monde ait accepté (et certains aient adopté) ce fait il y a longtemps.

Quant aux questions sur les raisons pour lesquelles certaines sont "spéciales" et n'ont pas besoin d'être déclarées, je ne pense pas que quiconque s'opposerait à l'existence d'une liste de directives critiques de "bas niveau" qui sont si omniprésentes qu'elles justifient d'être "béni". disponible dans le monde entier par le titulaire de la plate-forme (équipe Angular).

Si le code est déjà présent pour gérer le hissage des directives dans un seul ngModule, et que ce code fonctionne de manière invisible pour l'utilisateur final, quel est le mal à autoriser les deux approches ? C'est une vraie question, car je ne suis peut-être pas au courant de certaines des subtilités de ce qui pourrait arriver si un développeur mélange et associe l'approche. Il existe de nombreux autres "choix fractionnés" dans Angular 2 - formulaires basés sur des modèles ou basés sur des modèles, 3 choix de langage différents, décorateurs d'entrée/sortie/hôte vs approche de propriété - quel est le mal dans un autre à ce stade?

Je pourrais continuer, mais ce que j'essaie de faire valoir, c'est que l'équipe et la communauté Angular ont investi pas mal de temps pour faire passer le message qu'être plus explicite est une _bonne_ chose, seulement pour se précipiter - à _release candidat 5_ de tous les temps - pour nous présenter une solution qui n'a pas posé de problème depuis un certain temps.

Quelqu'un de l'équipe a-t-il envie d'intervenir ? Je ne veux pas que cela devienne une chambre d'écho - j'aimerais entendre l'autre côté de l'argument. Il semble juste que quelque chose d'aussi grand soit sorti de nulle part sans tenir compte de choses comme l'outillage, la formation ou à quel point nous sommes apparemment proches de la version finale.

Cette discussion a soulevé un très gros problème pour de nombreux développeurs qui souhaitaient commencer à développer tôt avec le très attendu angular 2 : breaking changes. J'ai fait un tas de preuves de concept basées sur angular 2 depuis la bêta 17 et j'ai fait en sorte que d'importantes entreprises et organisations l'adoptent. Je ne regrette pas mais je ne suis pas sûr d'avoir bien fait non plus. Certains des projets les plus récents étaient un POC et la bataille était contre Vue.js. Angular 2 a clairement remporté ce combat haut la main. Mais aujourd'hui, avec toute la réécriture du code, les changements cassants, la sortie pas vraiment RC, les gens commencent à me poursuivre et ça devient assez sérieux. Cela n'aurait pas été le cas si j'avais proposé un développement Vue ou React et c'est très frustrant à cause du discrédit que Angular 2 peut mettre les gens.

Il me semble très bien que je ne partage pas la même définition de Release Candidate que l'équipe Angular.

En ce qui concerne le sujet, le NgModule, je cosigne totalement @jpsfs , si vous devez lister tous vos composants et micro-composants dans votre déclaration de module, vous feriez mieux d'avoir une fonction prune quelque part ou d'être le roi de la modélisation car tout puissant soit-il, il est trop sensible pour des projets de grande envergure...

Je pense que ce niveau de modularité supérieur supplémentaire était presque inévitable ; et que divers cadres concurrents finiront par aboutir à quelque chose d'analogue.

Je me demande cependant s'il était vraiment nécessaire de rendre ce nouveau système de modules à gros grains complètement orthogonal au système de modules sous-jacent, ou s'il aurait été possible de rendre chaque répertoire de niveau supérieur, et tous les modules Es6 qu'il contient, implicitement comprennent un NgModule à gros grains. Peut-être qu'un tel mécanisme basé sur une convention pourrait être ajouté au mécanisme actuel, et donc supprimer le passe-partout NgModule pour les projets souhaitant suivre une telle convention.

(Bien sûr, je partage aussi la frustration avec d'autres ici, face à des changements aussi importants dans l'étape "RC"... Je suis sûr que l'équipe de base, si elle avait tout à refaire, aurait attaqué le haut niveau modularité, et les forces qui l'animent (lazy loading, pré-compilation) beaucoup plus près du début du projet plutôt qu'au stade de la release candidate. Telle est la vie cependant, il est toujours facile de regarder en arrière et de penser "bien si nous savions alors ce que nous savons maintenant...")

Si la prise en charge de la compilation est la principale raison de l'apparition du ngModule, il ne devrait certainement pas remplacer la portée basée sur les composants existants pour les directives et les canaux.
D'autre part, en se basant sur la configuration de la route et les dépendances, le compilateur angulaire pourrait théoriquement lui-même diviser le code de l'application en unités de compilation appropriées (modules).

Personnellement j'ai l'impression que ce changement apporte une basse passe-partout sans grand avantage.

Je pourrais dire qu'au lieu d'utiliser des modules, nous aurions pu utiliser des composants comme unités de l'application. C'est probablement ce que les gens faisaient avant rc-5 de toute façon.

Si les modules sont nécessaires à des fins internes de ce cadre (comme le chargement paresseux et les choses connexes), ils doivent être cachés au développeur d'une manière ou d'une autre afin de ne pas polluer le code et d'aggraver l'expérience de codage. Et je ne parle même pas de la maintenabilité...

La première fois que j'ai vu angular2, j'ai pensé: "Hé, ils vont dans la bonne direction avec ça, on dirait qu'ils ont appris quelque chose d'angular 1". Vous avez abandonné les modules internes d'angular 1 et utilisé à la place des modules ES, d'autres modifications ont également été les bienvenues (composants, tapuscrit, etc.)

Mais plus j'attends que cela se stabilise, plus cela me fait grincer des dents à cause des changements cassants, du manque de documentation et des messages d'erreur médiocres. Maintenant, vous venez avec ces NgModules et annulez essentiellement au moins une grande chose que vous avez modifiée depuis angular 1.

Pire encore, si j'ai une application qui a commencé avec rc-2 ou 3 (qui étaient théoriquement presque stables), je dois maintenant faire beaucoup de travail pour créer une bonne application angular2 rc-5 et j'ai besoin d'expliquer d'une manière ou d'une autre le client et les autres développeurs cela. Et même si je le fais, Dieu sait ce que vous changerez ensuite et mon travail aurait pu être vain.

Je sais qu'angular 2 en est à ses débuts depuis un certain temps maintenant, mais nous sommes RC-5, les gens ont des projets assez solides utilisant Angular 2 maintenant et vous faites toujours des changements non seulement en rupture du point de vue de l'API mais en rupture comme un moyen de penser en Angular.

Ce n'est pas bon ngFor et certaines importations changent ou que l'injection de composants change dynamiquement 3 fois en 5 versions, mais cela, je peux l'accepter et le comprendre. Apporter des changements qui cassent non seulement les applications, mais aussi la façon dont les développeurs pensent dans ce cadre si tard dans le cycle de développement, je ne peux malheureusement pas les accepter.

Quoi qu'il en soit, comme vous pouvez le voir, beaucoup de gens sont d'accord avec ce que j'ai à dire et certains sont encore plus en colère. Vous avez un énorme framework auquel les gens font confiance (parce que Google principalement) mais vous ne pouvez pas tout miser dessus ou vous pourriez avoir une surprise puisque tout le monde a des choix (et quand on parle de JS, il y en a BEAUCOUP).

Si le nouveau module avait un modèle, il pourrait s'agir du composant. Pensez-y.

L'étape suivante consisterait à déplacer toutes les variables et fonctions de Components vers la classe Module. Sérieusement. Ensuite, nous avons eu une énorme bibliothèque centrale de _toutes les actions possibles_ dans notre module brillant. Ce serait génial ! Je ne sais pas pourquoi vous vous êtes arrêté à la centralisation des déclarations et des dépendances. Il y a beaucoup plus de lignes de code décentralisées et structurées là-bas !

Quelqu'un de l'équipe de base peut-il avoir son mot à dire sur tout cela ? D'après les notes de la dernière réunion hebdomadaire, l'équipe va de l'avant avec la suppression des API obsolètes.

@mhevery

Toute cette affaire de levage a cassé mon application très subtilement lorsque j'ai mis à jour aujourd'hui.

  • J'ai dû changer le sélecteur d'un composant de classe en élément, car dans un composant totalement indépendant, cette classe est utilisée pour le style et a soudainement commencé à instancier le composant.
  • Je suis à peu près sûr que # 10850 n'existe que, car j'avais deux composants appelés SpectrumComponent (une page entière pour naviguer sans sélecteur et un composant "partagé" utilisé dans plusieurs composants pour la visualisation avec sélecteur). Le hissage est probablement confus - les déclarations directives: ne le sont pas.

Pour mes composants SVG, cela devient maintenant un problème plus important, car je ne peux pas y utiliser d'élément personnalisé. Je ne sais pas encore comment les définir pour m'assurer que leurs sélecteurs de classe ne déclenchent pas d'instanciation de composant ailleurs (!) Dans l'application.

Il semble être à la mode ces jours-ci d'ignorer la signification de "Beta" et "Release Candidate" (ASP.NET Core étant un autre exemple très médiatisé) dans les grands projets. Mais être confronté à des changements de rupture qui ont le potentiel de casser silencieusement une application littéralement n'importe où est plus frustrant qu'il ne devrait l'être. J'espère vraiment que les promesses qui accompagnent ces changements porteront bientôt leurs fruits.

ngModules a du sens. La suppression de la possibilité de déclarer/fournir au niveau du composant ne le fait pas.

Petit exemple

J'ai une application qui contient un certain nombre de boîtes de dialogue différentes (certaines simples - appelons-les simple-1 et simple-2, et une complexe qui contient d'autres composants - appelons-la complexe 3).

Pour le moment, j'ai une structure de dossiers simple (évidemment, l'application se trouve en dehors de cela)

- dialogs
   - simple-1 (containing single component and template for simple-1 dialog)
   - simple-2 (containing single component and template for simple-2 dialog)
   - complex-3 (contains the main complex-3 component plus a number of other internal components)
      - internal-component-1
      - internal-component-2
      - internal-service-3

Pour moi, c'est un ensemble de fonctionnalités parfait à mettre dans un module de fonctionnalités isolé. Alors j'ajoute

   dialogs.module.ts
   - simple-1
   - simple-2
   - complex-3
      - internal-component-1
      - internal-component-2
      - internal-service-3

Et j'ajoute Simple1Component, Simple2Component et Complex3Component comme déclarations à DialogsModule. Parfait, fonctionne bien et prend tout son sens.

Mais...

Qu'en est-il de tous ces composants internes dans le complexe-3. J'ai maintenant deux options

  • Ajoutez tous les composants et services complexes externes à DialogsModule. C'est une mauvaise décision car cela casse l'encapsulation de complex-3 car maintenant tout dans le module de dialogues connaît ses composants internes (internal-component-1, internal-component-2, internal-service-3)
  • Faites de complex-3 un module à part entière. Cela résout le problème de portée (et je crois que je peux exporter des modules à partir d'un autre module afin que le client n'ait qu'à importer le module wrapper) mais me laisse maintenant avec un mélange de composants et de modules pour des groupes similaires (dialogues).

Ni l'un ni l'autre n'a vraiment de sens, et à mesure que l'application évolue, le conflit entre les deux ne fera qu'augmenter.

La seule solution sensée/évidente/maintenable pour moi serait d'utiliser le module pour exporter les composants de niveau supérieur (simple-1, simple-2, complexe-3) mais laissez le complexe-3 _component_ définir lui-même ses propres composants internes.

/ cc : @robwormald

J'ai pensé à ce que @kylecordes a dit plus tôt à propos de l'utilisation du système de modules Typescript existant pour définir des collections de code de grain de course, plutôt que d'ajouter le nouveau ngModules. Je voudrais soumettre un exemple pour examen, qui utilise des modules Typescript pour définir ngModules de manière 1 à 1. Les commentaires et réflexions sont les bienvenus.

https://github.com/jbalbes/autoNgModule

10901

J'ai peut-être manqué quelque chose, mais la façon dont l'injection de dépendance fonctionne avec des modules non chargés peut devenir un gros problème pour les "grands projets" (le mien ne l'est pas et il souffre déjà).

c'est intéressant. nous avons déjà une application d'entreprise sur Angular1. et nous utilisons requirejs pour définir des packages pour différents modules (chaque module contient 10 à 20 directives/services/filtres). nous regroupons ces packages dans un seul fichier pour la production (à l'exception des directives principales). Les directives sont chargées paresseusement dans l'application lorsqu'elles sont utilisées (nous avons une directive principale qui charge paresseusement les directives requises).

nos modèles de page de routage d'application sont hébergés dans l'application cms, et les utilisateurs cms peuvent faire glisser/déposer des widgets d'interface utilisateur basés sur la directive principale entre différents modèles de page (c'est pourquoi nous avions besoin d'un support de chargement paresseux pour la directive afin de réduire la taille du fichier de script principal lors du chargement du navigateur comme la plupart de notre application est basée sur des widgets basés sur des directives)

Angular1 permet de charger paresseusement des directives sur un module en obtenant une référence pour enregistrer les fournisseurs.
est-ce que ce type de chargement paresseux de composants dans un module et de les compiler en dom est possible dans Angular2 ?

Je suis d'accord avec ce que d'autres ont suggéré que ngModules est une solution à la recherche d'un problème. L'avantage potentiel de LazyLoading dans mon esprit ne justifie pas la dépréciation forcée des dépendances des directives/tuyaux des composants. Peut-être que je me trompe ici, mais j'ai l'impression que la majorité des applications ne verront aucun avantage réel du Lazy Loading, qui pour moi est le seul véritable avantage fourni par ngModules.

Peut-être que ngModules essaie (et bon, peut-être qu'il réussira) de rendre la structure/les modèles de développement plus agréables, mais sur la base du peu que j'ai regardé et discuté de l'API jusqu'à présent, il évolue dans une direction qui est juste plus compliquée à suivre et entretenir.

Aussi, avons-nous vraiment besoin d'un autre système de modules ?

Personne ne peut contester que NgModule ajoute un nouveau type de chose que nous n'avions pas à gérer auparavant. Et j'apprécie autant que quiconque la simplicité pré-RC5, en particulier des très petits programmes, qui a été perdue. Cela me manque aussi beaucoup de pouvoir dire aux gens qu'Angular 1 avait son propre système de modules, mais avec Angular 2, nous utilisons simplement le système de modules du langage sous-jacent. Oups.

Cependant, il y a en fait beaucoup de gens, y compris de nombreux responsables techniques et autres décideurs de grandes entreprises essayant de construire de grandes choses, qui sont extrêmement intéressés par le chargement paresseux et la pré-compilation de modèles... Les deux sont considérablement activés par NgModule.

Encore une chose cependant. La partie que j'aime le moins dans les nouveaux modules Angular est le nom. Le mot module, lui, est tellement surchargé. J'en parlais pour d'autres développeurs ici hier, et nous aimons un peu le mot "paquet" à la place, il capture bien une idée similaire et il n'y a pas un tas de choses concurrentes avec le même nom, du moins pas dans l'écosystème JavaScript.

@kylecordes question sur le nom https://github.com/angular/angular/issues/10087

La logique qui y est présentée n'exclurait-elle pas également l'utilisation du mot « module », puisqu'il entre en conflit avec autant, sinon plus, de concepts ?

@Barryrowe n'aurait pas pu mieux le dire moi-même - il semble vraiment que la majorité des applications n'en bénéficieront pas - cela finit-il simplement par être une complexité supplémentaire? J'espère que non.

Je me demande cependant s'il était vraiment nécessaire de rendre ce nouveau système de modules à gros grains complètement orthogonal au système de modules sous-jacent, ou s'il aurait été possible de rendre chaque répertoire de niveau supérieur, et tous les modules Es6 qu'il contient, implicitement comprennent un NgModule à gros grains. Peut-être qu'un tel mécanisme basé sur une convention pourrait être ajouté au mécanisme actuel, et donc supprimer le passe-partout NgModule pour les projets souhaitant suivre une telle convention.

C'est un point clé. Les ESModules fonctionnent très bien pour structurer une application si vous structurez correctement votre application. Par exemple, vous pouvez facilement rendre disponible une exportation profondément imbriquée au niveau supérieur de votre API en la réexportant simplement à un niveau supérieur. Je suis également favorable à l'ajout de conventions supplémentaires, facultatives, au cadre en général.

La première fois que j'ai vu angular2, j'ai pensé: "Hé, ils vont dans la bonne direction avec ça, on dirait qu'ils ont appris quelque chose d'angular 1". Vous avez abandonné les modules internes d'angular 1 et utilisé à la place des modules ES, d'autres modifications ont également été les bienvenues (composants, tapuscrit, etc.)

Mais plus j'attends que cela se stabilise, plus cela me fait grincer des dents à cause des changements cassants, du manque de documentation et des messages d'erreur médiocres. Maintenant, vous venez avec ces NgModules et annulez essentiellement au moins une grande chose que vous avez modifiée depuis angular 1.

En effet, Angular 2 était censé tirer parti de la riche pile de technologies Web émergentes qui n'était pas disponible lors du développement d'AngularJS. Pourtant, alors que la justification de tant de décisions de conception prises pour Angular 2 a été "les composants Web doivent être pris en charge", ironiquement, le cadre s'écarte des normes de manière toujours plus importante. Maintenant, il y a de bonnes raisons de s'écarter de la norme, lorsque les normes sont mauvaises.

J'ai l'impression que le framework n'utilise pas pleinement ses outils de base. Par exemple, les déclarations TypeScript ne sont pas exactement idiomatiques et sont parsemées de any et any[] . Ils ignorent également les puissantes fonctionnalités du langage qui améliorent la convivialité et l'utilité des API. Ils contiennent également des choses odieuses comme export declare type Type = Function .

Fait intéressant, il semble qu'un bon nombre de décisions se soient avérées liées à Dart. Dart n'est pas quelque chose dont la plupart des utilisateurs d'Angular se soucient. Il a une notion très différente de ce que sont les types et de la façon dont ils sont utilisés par rapport à TypeScript. L'interopérabilité Dart <-> JavaScript est souvent un non-démarrage.

@aluanhaddad , la mise en œuvre de la fléchette a été récemment intégrée à un projet distinct, alors j'espère que certaines de vos préoccupations seront bientôt résolues.

Ce changement a ajouté un degré significatif de complexité, à la fois en termes de LOC global et de modélisation mentale des dépendances des composants. Mes fichiers de composants sont légèrement plus propres, mais au détriment d'une définition de dépendance explicite et sur place, et s'accompagnent de l'ajout de fichiers .module de sentiment redondants.

Réduire le passe-partout semble être une bonne chose, mais je dirais que cela peut être exagéré. En outre, il semble que cet effort particulier de réduction passe-partout soit mieux décrit comme un mouvement passe-partout plutôt qu'une réduction pure et simple.

Je pense qu'angular tend vers des démarrages rapides plus difficiles et complexes. Il y a déjà pas mal de choses à gérer en termes de configuration de la chaîne d'outils et de la liste des fichiers et des choses qui doivent être comprises (si l'on veut adhérer aux meilleures pratiques) car même l'application la plus simple augmente.

. @jbalbes merci, c'est bon à entendre.

@radusuciu vous avez absolument raison, il ne s'agit pas d'une réduction du passe-partout mais d'un transfert de ce passe-partout vers un autre domaine de l'application. Comme cela a déjà été dit par d'autres, il n'y a pas ici de conflit entre la portée au niveau des composants et la portée au niveau NGModule. Ce dont nous avons besoin, c'est d'une portée granulaire permettant de choisir les composants, les directives, les canaux et les services qui doivent être disponibles pour réduire les déchirures de l'application en fonction de leur utilisation et de leur sémantique spécifiques à l'application.

Il n'est pas étonnant pour moi que les modules ajoutent encore plus de complexité d'une valeur réelle douteuse à l'auteur de l'application. Ils ne faisaient pas partie de la conception originale et semblent être un ajout tardif uniquement parce que d'autres choses se heurtent à un mur et ne peuvent pas fonctionner (chargement paresseux, compilation, etc.) sans qu'un autre changement majeur ne soit apporté.

Je ne pense pas que toutes les implications pour le développement d'applications par rapport à "faire fonctionner les autres fonctionnalités promises" étaient aussi importantes à l'ordre du jour lorsqu'elles ont été ajoutées, mais à mesure que de plus en plus d'applications plus grandes sont converties en RC5, elles commencent à devenir plus claires.

Je n'ai même pas commencé à essayer de convertir mon application en modules, elle mourra probablement sur RC4. Je sais que tant de pièces devront être complètement retravaillées et tout ce que j'obtiendrais pour tous ces efforts est d'être plus proche du prochain changement de rupture RC avec des bundles d'exécution encore plus grands parce que la minification, sûrement quelque chose d'assez basique et fondamental, est cassé . Les RC sont censés devenir plus stables et se sentir plus finis à mesure qu'ils progressent, ce n'est tout simplement pas le cas.

Gang, NgModule est une irritation comme beaucoup l'ont expliqué avec éloquence. Mais pratiquement ce n'est pas si grave que ça. Ici (Oasis Digital / Angular Boot Camp), nous avons déjà mis à jour de nombreuses petites choses, et quelques-unes pas si petites, sur RC5, et cela a été fait en peu de temps (après un long moment d'étude et de compréhension).

L'application de chacun sera affectée différemment. De plus, je pense que votre attitude à l'égard du désabonnement et du changement dans Angular 2 sera peut-être différente si vous vous concentrez sur la livraison d'une application ou si vous vendez également une formation et une assistance pour Angular 2. Pour moi, tout le travail de mise à niveau vers RC5 serait être complètement mort et inutile - cela apporterait en fait des avantages négatifs (plus gros lots) et est donc difficile à justifier.

Je pensais juste que je donnerais mes pensées en sortant du revers d'une poussée de cinq jours sur notre plate-forme pour arriver à RC6 * (nous sommes sur des nightlies, RC6 n'a pas encore baissé techniquement au moment de la rédaction). Je pense que même si mes commentaires initiaux sont toujours valables, il y a un sentiment de soulagement d'avoir atteint cette étape. Les plus grandes difficultés continuent d'être l'utilisation de la nouvelle syntaxe de routage - beaucoup trop de règles vides path: '' ! (Je m'égare) mais c'est quelque chose que nous allons probablement faire abstraction.

Pour NgModules sur les nightlies, je dois dire que les messages d'erreur s'améliorent, ce qui rend l'ensemble du processus un peu plus facile à utiliser. Les composants et les directives sont généralement appelés lorsqu'ils ne sont pas configurés correctement avec suffisamment d'informations pour que vous ne parcouriez pas une arborescence de dépendances NgModule massive pour trouver le problème. Le principal problème que nous rencontrons maintenant est simplement la fonctionnalité manquante sur les pages sans messages d'erreur évidents. Cela est généralement dû au fait qu'un composant n'a pas été déclaré ou importé/exporté correctement. C'est un peu délicat, mais avec l'éducation, c'est assez facile à gérer. Les tests sont maintenant notre prochaine poussée, c'est complètement mort dans l'eau. Mais comme la poussée de fonctionnalité, nous y arriverons à la fin.

Nous avons pris une profonde inspiration, avons fait autre chose pendant quelques jours, puis nous l'avons brisé. On tient bon pour la prochaine sortie, quelle qu'elle soit ! Bonne chance à tous ceux qui sont touchés par cela d'une manière petite ou grande. Cela aurait été bien d'avoir une sorte de dialogue avec l'équipe Angular sur celui-ci. Le problème le plus difficile auquel nous avons été confrontés était le manque de communication. Nous ne savons toujours pas ce qu'il y a sur les cartes pour NgModules. Les notes de réunion de la semaine dernière n'offraient aucune information. Voyons ce qui se passe cette semaine !

@SaltyDH Je pense que ce sont des commentaires précieux.
Je pense que les plaintes concernant la communication ne sont pas vraiment appropriées.

Les personnes chargées de l'implémentation construisent la nouvelle version et les personnes chargées de la documentation mettent à jour la documentation.
Les documents sont généralement un peu en retard pour des raisons évidentes, car ils ne peuvent documenter qu'une fois qu'ils ont déjà été codés. La rédaction de documents est également un travail difficile et chronophage.

Si vous passez à la version suivante le jour de sa sortie ou même en utilisant des nightlies, c'est un peu injuste de se plaindre que tout n'a pas encore été communiqué.
L'équipe Angular ne peut pas non plus savoir à l'avance ce qui pourrait causer des difficultés à l'utilisateur dans tous les cas.

Il y a toujours des membres de l'équipe Angular qui fournissent une assistance sur Gitter et les problèmes.
Vous devez également être conscient que la charge de communication est assez asymétrique, avec quelques membres de l'équipe Angular pour des milliers de développeurs.

Je suis tout à fait d'accord que c'est plus facile sur la version principale (presque-RC6) avec la dernière année + de dépréciations qui disparaissent enfin.

@kylecordes en quoi est-il plus facile de travailler avec le master ?

Le document de conception pour NgModules (anciennement connu sous le nom d'AppModules lors de la rédaction du document de conception) a été publié il y a plus d'un mois avant la sortie de RC5, et j'étais en quelque sorte préparé à ce qu'il vienne.
De plus, étant donné que NgModule était un concept plus récent, il était difficile de le saisir complètement et de migrer votre application moyenne à grande.
Ce que j'ai fait à la place, c'est d'abord comprendre complètement les nuances de NgModules et comment penser dans NgModules pour concevoir une application Angular 2. Puis créé une application d'auto-apprentissage avec l'application de NgModules.
La deuxième étape consiste à réfléchir à la manière dont l'application actuelle peut être divisée en modules, puis à les migrer de haut en bas. créer un module à la fois en commençant par AppModule. Cela a vraiment aidé et l'application finale semble plus organisée.
image

Et oui, Gitter a été très utile pour fournir de l'aide sur NgModule avant même la sortie de RC5. Après RC5, nous avons des documents et des blogs disponibles pour que nous puissions apprendre beaucoup mieux.

@zoechi Sans trop faire dérailler cette discussion, je sens que je dois clarifier mes commentaires. Je ne faisais pas du tout référence à la documentation, la plupart de mes compréhensions sont venues de l'examen des commits et des problèmes ici dans GitHub, ça me va. Mes frustrations viennent d'un manque de représentation ici dans ce numéro, nous en sommes à 61 commentaires et nous comptons. Un simple, "Nous sommes conscients des préoccupations de chacun ici dans ce numéro, nous croyons vraiment que c'est la meilleure approche pour Angular 2 et nous reconnaissons les difficultés que cela causera mais c'est mieux pour l'avenir du produit". Gitter est génial, mais les messages individuels se perdent souvent dans une mer de personnes essayant de comprendre différents aspects d'Angular 2. pourrait utiliser pour prendre une décision éclairée. Ce qui a aidé, c'est ce podcast Adventures in angular https://devchat.tv/adv-in-angular/106-aia-angular2-rc5-and-beyond. Cela m'a donné la confiance nécessaire pour aller de l'avant avec les mises à niveau de NgModule.

Tous mes vœux.

Merci pour les commentaires à tous, excuses, il a fallu si longtemps pour obtenir une réponse - nous avons été très occupés la semaine dernière (migration des applications Google internes vers NgModules, nous ressentons donc également la douleur de la refactorisation)

Permettez-moi de voir si je peux éclaircir certaines des questions et des idées fausses ici.

La première chose à comprendre à propos de @NgModule() (et de @Component et de tout autre décorateur Angukar) est qu'ils sont purement construits au moment de la compilation - ils existent pour permettre au compilateur angulaire de découvrir un graphe de dépendance dans une application.

Une version (simplifiée) de ce que font nos décorateurs ressemble à :

//simplified Component decorator
export function Component(componentConfig){
  return function(componentClass){
    Reflect.defineMetadata('annotations', componentConfig, componentClass);
  }
}

Ils ne changent ni ne modifient en aucune façon le comportement de la classe décorée - ils attachent simplement des métadonnées. Angular utilise ces métadonnées pour construire votre application et compiler des modèles.

En mode JiT, cela se produit "juste à temps" - entre l'appel de bootstrapModule et le rendu de votre premier composant, le compilateur d'Angular récupère les métadonnées attachées aux classes à l'aide de l'API Reflect :

let metadata = Reflect.getOwnMetadata('annotations', componentClass);

En mode AoT cependant, cela fonctionne un peu différemment - au moment de la construction, nous extrayons _statiquement_ (c'est-à-dire sans exécuter votre code) les mêmes métadonnées du code source en recherchant des décorateurs.

Cela fonctionne bien lorsque vous démarrez un seul composant, mais nous avons entendu beaucoup de commentaires de développeurs qui font des choses plus complexes - démarrage de plusieurs composants racine, ou démarrage de différents composants en fonction du statut d'authentification, etc.

Ainsi, alors que les décorateurs @Component nous donnaient la possibilité d'analyser statiquement un composant, nous n'avions pas la possibilité d'analyser statiquement de manière fiable une _Application_

Choses qui relèvent d'une "application"

  • PLATFORM_DIRECTIFS/TUYAUX/FOURNISSEURS
  • choses que vous avez précédemment ajoutées à bootstrap()
  • paramètres au niveau du compilateur
  • plusieurs composants racine
  • utilisation côté serveur.

Les NgModules introduisent l'idée d'un ensemble de fonctionnalités analysables statiquement. Ce qui est intéressant, c'est qu'en mode compilation AoT, nous analysons votre module racine et _générons_ une ModuleFactory pour chaque module de l'application - il s'agit de la version pré-compilée d'un module, qui contient _uniquement_ les fabriques que vous référencez statiquement dans les modèles et celles que vous marquer comme "entryComponents"

Parce que nous avons déjà extrait les informations nécessaires à la compilation à l'avance, nous pouvons en fait secouer les décorateurs (ngc s'en chargera automatiquement pour la version finale) - et plutôt que de regrouper votre application en commençant par votre module racine, vous démarrez à votre racine générée Module_Factory_, qui ne contient que le code réellement utilisé dans votre application, vous ne payez donc pas de pénalité pour la modularité, et des outils comme rollup et webpack2 peuvent fonctionner _plus_ efficacement

plus à suivre dans la prochaine réponse...

@robwormald Je ne peux pas mettre dans un emoji la quantité d'appréciation pour ce genre d'informations de fond.

Merci!

Un autre problème que nous avons rencontré et que NgModules résout :

Considérez un cas où vous souhaitez créer un DialogService ou similaire.

Historiquement, vous feriez quelque chose comme :

@Injectable()
export class MyDialogService {
  //inject the dynamic compiler 
  constructor(private componentResolver:ComponentResolver){}

  //accept a component and a viewContainerRef
  showDialog(component:Type, target:ViewContainerRef){
    //compile the component into a factory, async
    return this.componentResolver.resolveComponent(component)
      .then(componentFactory => {
         //dynamically insert the compiled componentFactory into the view:
        return target.createComponent(componentFactory);
      })
  }
}

... que vous utiliseriez comme

myDialogService.showDialog(MyRandomDialogComponent).then(...)

Choses à remarquer ici -

  • la compilation des composants en mode JiT _doit_ être asynchrone, à cause des templateUrls et styleUrls externes
  • un viewContainer accepte un _componentFactory_ - donc maintenant votre code a un problème : vous devez soit réécrire le code pour changer de mode (entre JiT et AoT), _ou_ vous devez toujours supposer que l'API d'insertion de composant est asynchrone. Cela peut convenir dans le cas d'une boîte de dialogue, mais si vous construisez des interfaces utilisateur complexes de manière dynamique (pensez à un tableau de bord ou à une vue de grille ou autre), vous encourez une énorme quantité de planification de promesse inutile.
  • Les services/composants tiers ou partagés (comme SharedDialogService) ont le même problème, devant accepter _soit_ Composants ou ComponentFactories

Ce problème survient pour _toute_ application qui effectue une insertion dynamique de composants (ce qui ne signifie pas nécessairement un chargement paresseux) - les dialogues, les routeurs, etc., s'attendent tous à interagir avec les ComponentTypes (les classes) au lieu des sélecteurs (foo-bar).

Ainsi, lorsque vous ajoutez un Component à votre tableau entryComponents dans un décorateur NgModule :

@NgModule({
  declarations: [ MyRandomDialogComponent ],
  entryComponents: [ MyRandomDialogComponent ]  
})
export class MyApp {}

Ce que cela indique au compilateur est "générez-moi un mappage entre MyRandomDialogComponent et son MyRandomDialogComponentNgFactory compilé", et _stockez-le dans le NgModuleFactory dans lequel il est déclaré_

Ainsi, une version pilotée par NgModule du dialogService ci-dessus ressemble à :

@Injectable()
export class MyDialogService {
  //inject the component factory resolver 
  constructor(private componentFactoryResolver:ComponentFactoryResolver){}

  //accept a component and a viewContainerRef
  showDialog(component:Type, target:ViewContainerRef){
    //*retrieve* the componentFactory by component, sync
   let componentFactory = this.componentFactoryResolver.resolveComponentFactory(component)
   //add the componentFactory to the view, sync
   return target.createComponent(componentFactory);
  }
}

Désormais, tout composant que vous avez ajouté à entryModules peut être récupéré de manière synchrone et inséré dynamiquement dans la vue, et votre code n'a _pas_ à changer en fonction du mode dans lequel vous vous trouvez, et les bibliothèques tierces/partagées n'ont pas à se soucier de la compilation logique.

Merci pour l'explication @robwormald

Une question est la suivante : cela nécessite-t-il la suppression des déclarations de directive/pipe ? Y a-t-il une raison pour laquelle ils ne peuvent pas coexister avec NgModule ?

J'ai l'impression que les gens, y compris moi-même, ne sont pas frustrés par le "petit nouveau sur le bloc" NgModule ou par tout malentendu à son sujet, mais que "l'ancienne façon" de faire les choses, qui semble _fonctionner bien_ avec beaucoup de gens, est en train d'être retiré de force, surtout à ce stade tardif de RC. Je pense que c'est une distinction importante par rapport à toute résistance à NgModule lui-même, dont je n'ai pas beaucoup vu, qui n'a pas encore été directement abordée.

Je vois également que la demande d'extraction pour la suppression des déclarations de directive/pipe est en place (https://github.com/angular/angular/pull/10912) - J'espère que nous pourrons obtenir une réponse sur ce point avant que quoi que ce soit ne soit défini Pierre.

Merci d'avance. Angular a sans aucun doute été une joie de travailler avec et j'apprécie beaucoup le travail acharné de l'équipe au cours de la dernière année +

Il y a quelques commentaires ici concernant la "portée globale" - cela comprend mal la mécanique du compilateur et des modules (ce qui est tout à fait compréhensible, c'est une chose complexe).

Le vidage de votre application entière dans un seul NgModule est "bien" de la même manière que le vidage de l'état de votre application entière sur $rootScope était "bien" dans Angular1 (lire : cela fonctionne, mais la conception de son application est médiocre)

Dans Angular 1, amener un module dans une application a plus ou moins "pollué" l'ensemble de votre application, car tout a été déversé dans un seul sac d'injecteur.

Dans Angular2, NgModues dispose de mécanismes de portée très puissants qui permettent une composition sans pollution. Encore une fois, cela revient au compilateur.

Lorsque Angular parcourt et compile votre application, chaque composant qu'il rencontre est _compilé dans le contexte dans lequel il a été déclaré_

Par exemple - imaginez que vous avez un SharedModule avec certaines fonctionnalités que vous souhaitez partager dans une application

@Component({
  selector: 'shared-component-one',
  template: `
    <div>Shared Component One</div>
    <shared-component-two>
  `
})
export class SharedComponentOne {}

@Component({
  selector: 'shared-component-two',
  template: `
    <div>Shared Component Two</div>
  `
})
export class SharedComponentTwo {}

@NgModule({
  declarations: [ SharedComponentOne, SharedComponentTwo ],
  exports: [ SharedComponentOne ]
})
export class SharedModule {}

SharedComponentOne et SharedComponentTwo sont _déclarés_ dans le SharedModule - les déclarations impliquent _ownership_ - donc ces deux composants appartiennent à SharedModule. Cependant, _seulement_ SharedComponentOne est _exporté_ du module - SharedComponentTwo reste _privé_ vers SharedModule.

Si vous deviez apporter SharedModule et l'utiliser dans un autre module, comme ceci :

@Component({
  selector: 'some-component',
  template: `
    <div>hello from some component</div>
    <shared-component-one></shared-component-one>
  `
})
export class SomeComponent {}

@NgModule({
  imports: [ SharedModule ],
  declarations: [ SomeComponent ]
})
export class SomeModule {}

... lorsque le compilateur commence à compiler SomeComponent , il découvre le sélecteur shared-component-one , et parce que SharedModule (qui exporte SharedComponentOne ) est importé dans SomeModule , il sait que composant-partagé-un === SharedComponentOne.

Fait intéressant, lorsque le compilateur compile réellement SharedComponentOne, il le fait "à l'intérieur" de SharedModule, ce qui lui permet d'utiliser des éléments de SharedModule qui ne sont pas exposés au monde extérieur.

Ceci est très similaire à la façon dont il fonctionnait avec Component.directives, et dans ce cas, ils sont égaux.

Considérez cependant si vous aviez quelque chose comme une fonctionnalité Tabs :

@Component({
  selector: 'my-tabs',
  template: '...'
})
export class TabsComponent {}

@Component({
  selector: 'my-tab',
  template: '...'
})
export class TabComponent {}

Ces deux composants sont de niveau supérieur, il n'y a pas de relation hiérarchique sur laquelle s'appuyer. Celles-ci ont conduit à l'explosion d'une sorte de convention de personnes faisant

export const TAB_DIRECTIVES = [ TabsComponent, TabComponent ]

Une fonctionnalité d'onglets plus compliquée peut avoir un service qui gère plusieurs instances d'onglets, vous devez donc également gérer ce cas...

export const TAB_PROVIDERS = [ ... ]

et l'utiliser devient un exercice pour se souvenir de tout ce que vous devez exporter et importer...

import {TAB_DIRECTIVES, TAB_PROVIDERS}

et ensuite fournir toutes ces choses au bon endroit _partout_ où vous voulez l'utiliser. Il est également très facile à ce stade d'oublier d'importer TOUTES les choses dont vous avez besoin pour une fonctionnalité et de vous retrouver avec des échecs silencieux étranges ou des composants compilés sans tout leur contexte requis.

Avec un NgModule, vous pouvez simplement les regrouper en une seule unité, la transmettre à votre application et l'importer le cas échéant.

Pour les bibliothèques comme Material Design, qui peuvent avoir un certain nombre de fonctionnalités réparties sur plusieurs modules, vous pouvez tirer parti de la même sémantique d'importation/exportation pour la rendre encore plus portable :

@NgModule({
  exports: [ TabsModule, NavbarModule ]
})
export class MaterialSharedModule {}

tirer ce module unique permet à toute votre application d'utiliser des composants, et encore une fois, au moment de l'AoT, seuls ceux que vous utilisez seront importés dans le code généré.

Quant à la raison pour laquelle nous avons supprimé Component.directives / pipes, nous avons entendu de nombreux commentaires dans les deux sens. Nous pensons qu'avoir deux façons d'accomplir la même chose est généralement un mauvais modèle, nous avons donc fait le choix de permettre aux gens d'écrire généralement moins de code, et ceux qui veulent la portée explicite précédemment offerte par Component.directives peuvent accomplir la _même_ fonctionnalité en portée au niveau du module.

Dans RC5, nous avons fait une sorte de levage automatique de Component.directives dans la portée "globale". C'était une tentative de faciliter la transition, et bien que cela ait fonctionné pour la plupart des gens, le comportement mixte ancien et nouveau a provoqué des erreurs et des comportements étranges qui, bien que frustrants, sont temporaires. Cela disparaît dans RC6 (et les messages d'erreur ont été améliorés)

Quant à savoir pourquoi cela a changé si tard dans le jeu - nous ne pouvons que nous excuser. Nous n'aimons pas plus que n'importe lequel d'entre vous faire des changements de dernière minute. En fin de compte, nous construisons littéralement un cadre d'une manière qui n'a jamais été faite auparavant, et nous rencontrerons donc des problèmes imprévus et des problèmes de conception. C'était l'un de ces cas, et il a été fortement débattu et étudié au sein de l'équipe de base avant de prendre la décision. Encore une fois, nous sommes désolés pour le dérangement, mais nous sommes convaincus que le résultat net est une façon beaucoup plus agréable de créer des _applications_, c'est pourquoi nous sommes tous ici.

Merci pour la patience de chacun. Je laisserai cela ouvert s'il y a d'autres questions que je n'ai pas abordées ici.

Rob

Beau travail, @robwormald

J'aimerais ajouter quelques observations supplémentaires :

Fournisseurs

Rob s'est concentré sur les _déclarations_, les _importations_ et les _exportations_. Les _fournisseurs_ de module sont différents.

@Component.providers vies ! Seuls @Component.directives et @Component.pipes s'en vont.

Vous pouvez utiliser à la fois @NgModules.providers et @Component.providers . Ils ont des finalités différentes :

a) @NgModules.providers _étend_ l'application en ajoutant des fournisseurs à l'injecteur "principal" (l'injecteur racine de l'application pour les modules chargés avec impatience). C'est ainsi que le RouterModule ajoute un service de routage à votre application sans que vous ayez à le fournir.

b) @Component.providers _encapsule_ la fourniture du service dans le cadre de l'instance de composant (et de son sous-arbre de composants).

Les deux approches répondent à des besoins différents.

Mon conseil général : _si vous avez un fournisseur sur @Component aujourd'hui, laissez-le là_

Modules de fonctionnalités

Ils constituent un moyen puissant d'organiser votre application. Le chapitre sur le module angulaire contient une courte section sur la refactorisation d'un module angulaire monolithique vers un module de fonctionnalités . C'est assez facile (du moins ça l'a été pour moi les plusieurs fois où je l'ai fait.).

Je recherche des coutures naturelles dans mon application. Je ne deviens pas fou. Je ne modularise pas chaque composant.

La raison pour laquelle Material Design semble le faire est qu'ils essaient de nous faciliter l'utilisation de ce que nous voulons de manière plus fine.

Ils auront un module évier de cuisine qui réexportera simplement tout. Vous pouvez simplement importer cela et être fait. Mais si je règle ma propre application, je crée un _module de réexportation_ similaire qui exporte uniquement les parties MD que je veux.

Il s'agit d'un modèle que tout fournisseur de bibliothèque pourrait suivre et qui pourrait avoir du sens dans l'entreprise où nous constituons nos propres "kits" de gadgets approuvés par l'entreprise.

Découverte des dépendances de déclaration

Le compilateur fait maintenant un bien meilleur travail pour vous dire quand quelque chose manque. Si vous suivez la pratique recommandée et coupez _toujours, toujours, toujours_ les noms de vos sélecteurs de composants, le compilateur vous dira quand vous avez un composant non déclaré. Il récupère également les liaisons de données et les directives non déclarées/non reconnues.

Migrer depuis le pré-RC5 favorise un sentiment de perte. Nous devons faire le travail fastidieux de découvrir les dépendances dans nos précédentes listes directives et pipes . Et nous devons dédoubler. C'est le désagrément essentiel de vivre sur le bord.

Un RC ne devrait pas changer autant

Ouais. Vous n'obtiendrez pas d'argument de l'équipe à ce sujet. Ce n'était pas intentionnel. Si nous avions su que nous avions besoin NgModule , nous l'aurions eu en version bêta.

Mais IMO, mieux vaut expédier le bon produit que de suivre servilement une idée de ce que devrait être un RC et de livrer le mauvais produit. Aussi ... et ce n'est pas très rassurant à dire ... mais si vous avez observé récemment d'autres grands éditeurs de logiciels, vous avez peut-être remarqué une notion tout aussi flexible de "release candidate". C'est la façon dont notre industrie va pour une raison quelconque.

J'ai converti un certain nombre d'applications maintenant et j'ai aidé d'autres à le faire. Une fois passée la phase "_ils ont déplacé mon fromage (encore)_", c'est une migration assez mécanique et tout le monde semble penser qu'ils sont dans un meilleur endroit. Peut-être qu'ils sont juste gentils avec moi. OTOH, je ne traîne pas avec des gens si gentils que ça ;-)

(aussi, re: le nom)
Nous avons échangé des noms à mort. Ils s'appelaient initialement AppModules (puisqu'ils décrivent quelque chose de plus haut qu'un composant, une "App") mais ce n'était pas un terme assez large. Colis, fagots, fûts, globs, etc.

Gardez à l'esprit que ce n'est pas un remplacement pour les modules ES - c'est une augmentation qui permettra aux modules tree shaking et ES de mieux fonctionner pour tous les développeurs angulaires, et sémantiquement, ils sont similaires au fonctionnement des modules ES (importations, exportations, déclarations)

Donc, nommer est difficile. C'est NgModule.

Nous avons terminé l'API pour la version 2.0.0, et nous surveillerons donc les prochains mois après la sortie pour voir quels modèles se développent et où nous pouvons sucrer et faire de meilleures inférences pour la 2.1.

Merci sincèrement @robwormald @wardbell pour les commentaires très perspicaces. Je pense que pour moi le plus grand soulagement est

"Nous avons terminé l'API pour la 2.0.0, et nous surveillerons donc les prochains mois après la sortie pour voir quels modèles se développent et où nous pouvons sucrer et faire de meilleures inférences pour la 2.1."

C'est quelque chose que nous avons déjà entendu il y a quelques semaines, mais c'est maintenant spécifiquement dans le contexte de NgModules avec tous ces commentaires. C'est la confiance dont j'avais besoin pour aller voir un conseil et dire. Nous avons terminé ici, il est temps de terminer la construction de notre application. Je tiens également à adresser mes félicitations à toute l'équipe et à la communauté ng2 pour avoir atteint cette étape ! Des temps passionnants à venir.

Je crois honnêtement que vous pouvez dire que @SaltyDH. Le désabonnement angulaire 2 est terminé.

Cela ne signifie pas que Angular 2 a fini d'évoluer. Il y aura de futures versions. Mais l'attrition menant à la 2.0... est... finie !

Merci beaucoup pour l'honnêteté et les cas d'utilisation explicites, les gars. Cela aide vraiment.

Juste une réflexion rapide sur la dénomination et la duplication dans l'API pour NgModule, ce qui me semble un peu lourd.

OMI ceci:

@NgModule({
  declarations: [ SharedComponentOne, SharedComponentTwo ],
  exports: [ SharedComponentOne ]
})
export class SharedModule {}

...pourrait être plus clair et plus concis comme suit :

@NgModule({
  private: [ SharedComponentTwo ],
  public: [ SharedComponentOne ]
})
export class SharedModule {}

1) WRT à la dénomination (public et privé vs déclarations et exportations), c'est essentiellement comment @robwormald ci-dessus et je suis sûr que beaucoup d'autres l'expliquent

2) (En ignorant la dénomination) pourquoi faudrait-il répéter SharedComponentOne ? Vous pourriez sûrement dire que s'il s'agit d'une "exportation", il doit s'agir d'une "déclaration", donc cela pourrait simplement être désucré de cette façon ?

Juste mes deux cents sur quelque chose de très subjectif 😄 - merci encore pour les explications détaillées !

@robwormald @wardbell Merci pour les explications détaillées.

Et comme je l'ai dit plus tôt dans ce fil, NgModules nous aide à mieux nous organiser. Un exemple récent est la création de directives de validation pour les formulaires basés sur des modèles. Avant RC5, nous devions importer chaque directive sur le composant où nous créons un formulaire. Maintenant, nous l'emballons simplement dans VaildatorModule et importons le module partout où cela est nécessaire. Tout validateur que nous ajoutons plus tard est automatiquement disponible pour les modules où j'ai importé ValidatorModule . J'ai juste besoin de mettre à jour le modèle sans me soucier des dépendances.

@JamesHenry declarations , imports et exports sont utilisés pour maintenir NgModules en ligne avec les modules ES6 comme nous import , export et declare trucs dans les modules ES6.
Je suis d'accord avec le sucre, les choses qui sont exportées peuvent être désucrées en déclarations automatiques comme par magie.

@JamesHenry

1), nous sommes restés avec les importations/exportations parce que le modèle mental est plus proche du fonctionnement des modules es (au moins en termes de portée) - vous déclarez des choses dans un module, importez des choses d'autres modules et exportez des choses pour les rendre disponibles à autres.

2) if it is an "export" it must be a declaration, so it could just be desugared that way? -> cela fonctionne jusqu'à ce que vous utilisiez un ngModule pour réexporter, comme dans l'exemple MaterialModule ci-dessus - il existe de nombreux cas où vous pouvez utiliser un ngModule pour réexporter quelque chose déclaré dans un autre module, et puis les inférences s'effondrent.

@robwormald Excellents commentaires ! mérite certainement un article de blog.

J'ai une bibliothèque de dialogue qui utilise @NgModule maintenant et je peux dire que je vois des utilisateurs se débattre en essayant d'ajouter des composants personnalisés car ils oublient de les enregistrer dans entryComponents , ce n'est apparemment pas assez clair mais compréhensible car il s'agit d'une fonctionnalité avancée...

Je suis sûr qu'il s'enfoncera avec le temps

@shlomiassaf merci !

Devrait également mentionner, pour des cas comme le vôtre :

Notez que lorsque vous utilisez le routeur d'angular, vous ajoutez des composants aux déclarations et à la configuration de la route, mais _pas_ à entryComponents, malgré le fait que le routeur est la définition même de entryComponents. (rappelez-vous - entryComponent === chose à laquelle vous voulez vous référer par classe, plutôt que par sélecteur)

Il y a une astuce sympa dont n'importe quelle bibliothèque peut profiter - il y a un jeton magique appelé ANALYZE_FOR_ENTRY_COMPONENTS - voir https://github.com/angular/angular/blob/master/modules/%40angular/router/src/ router_module.ts#L117 pour savoir comment le routeur l'utilise.

Ainsi, pour les bibliothèques qui traitent des composants insérés dynamiquement, vous pouvez faire quelque chose comme :

@NgModule({
  providers: [ DialogService ]
})
export class DialogModule {
  static withComponents(componentList): NgModuleWithProviders {
    return {
      ngModule: DialogModule,
      providers : [
         { provide: ANALYZE_FOR_ENTRY_COMPONENTS, useValue: componentList, multi: true }
      ]
     }
  }
}

utilisé comme

@NgModule({
  declarations: [ MyConfirmDialog, MyQuestionDialog ],
  imports: [
    DialogModule.withComponents([ MyConfirmDialog, MyQuestionDialog ])
  ]
})
export class MyAppModule {}

Peut fonctionner pour votre cas d'utilisation, peut-être pas.

@JamesHenry Très important que declarations ne soit pas confondu avec private . Vous dites que _Ce module déclare ce composant_. Vous ne faites aucune déclaration sur le public ou le privé. Vous revendiquez la propriété.

C'est vraiment comme ce qui se passe dans les modules ES6. Tout ce que vous définissez dans le fichier "appartient" au module défini par ce fichier. Qu'il soit public ou non dépend de votre utilisation du mot-clé export .

Et comme avec les modules ES6, vous _pouvez réexporter_ les éléments que vous avez importés.

J'aime penser à declarations comme "l'astuce" qui m'empêche d'avoir à placer physiquement tous mes composants, directives et tuyaux dans le même fichier physique (comme vous auriez à le faire avec les modules ES6 si vous vouliez toutes ces classes appartiennent au même module ES6).

Donc, pour moi, declarations remplace le collage de ces fichiers dans un très gros fichier. C'est _mon_ modèle mental de toute façon.

Une chose à noter est la différence logique entre les fournisseurs et les composants dans le contexte d'un module.

Les fournisseurs et les composants sont déclarés au même endroit ( NgModuleMetadataType ) afin qu'un développeur puisse intuitivement sentir que les fournisseurs se comportent comme des composants... ce qui revient à penser qu'un fournisseur dans un module se traduira par une instance pour ce module. .

Étant donné que les fournisseurs sont gérés par le DI, ce n'est bien sûr pas vrai, ils sont en fait au niveau de l'application.
Les composants d'un module sont privés s'ils ne sont pas exportés, cela peut prêter à confusion.

J'adore le concept de modules, IMO le seul problème dans l'API est d'avoir des fournisseurs et des composants déclarés au même endroit dans un module... pour les nouveaux arrivants, c'est une chose difficile à saisir.

@wardbell Merci Ward c'est vraiment super ! Juste pour clarifier car cela vient d'être soulevé dans les discussions, quand nous disons Angular 2 est l'API complète, de quels espaces de noms parlons-nous ici ? @angulaire/???

@robwormald Merci ! Une bonne astuce !!!
Un goût sucré ! mettra en œuvre.

Je ne suis pas un employé de Google et peut-être qu'un employé de Google ne pourrait pas le dire. Je ne peux que signaler ce que je vois de mes propres yeux : un gel très sérieux de l'API sur l'ensemble de bibliothèques @angular/ .

Il y a de bonnes idées qui restent sur l'étagère parce qu'elles n'étaient pas assez bonnes ou assez profondes pour justifier la tenue de la publication. C'est ainsi que cela devrait être. Les bonnes idées ne cessent jamais. Mais le moment est venu de dire _Ceci est votre Angular 2.0_.

Nous avons la suppression promise de l'API obsolète d'ici la "finale". Cela a des ajustements ... comme n'importe qui peut le voir en regardant le maître. J'ai l'impression qu'on a fini.

@wardbell Je fais écho à ce que vous dites sur les exportations.
L'index.ts était autrefois rempli de

export * from 'a.component'
export * from 'b.component'
export * from 'c.component'
export * from 'p.directive'
export * from 'x.service'
export * from 'z.pipe'

est maintenant réduit à seulement export * from my.module
reste tout ce qui est propre se trouve dans les exportations NgModule comme
exports: [ AComponent, BComponent, CComponent, PDirective ] et ainsi de suite

@wardbell Je pense que @NgModules.providers aurait dû être @NgModules.rootProviders ou @NgModules.appProviders .

Je pense qu'il décrit clairement le contexte des fournisseurs.

@shlomiassaf Ce serait trompeur. L'effet de @NgModules.providers est différent pour les modules impatients et paresseux. Les modules chargés en différé obtiennent leur propre injecteur enfant, ce qui signifie que _leurs fournisseurs_ sont ajoutés à l'injecteur _enfant_, et non à l'injecteur _racine_. Et ainsi de suite si un paresseux a chargé un paresseux a chargé un paresseux.

Peut-être aurait-il pu y avoir un autre nom. Tu sais comment ça se passe. Mais rootProviders n'aurait pas été une amélioration pour les raisons que je viens de donner.

@wardbell a accepté, n'a pas pensé à ce scénario.

Je voulais juste ajouter au sentiment que les réponses et la communication approfondies sont très appréciées. S'il s'agit bien de la dernière des difficultés de croissance du RC à la finale, nous partons pour les courses. Merci!

Comme d'autres l'ont fait remarquer, les commentaires de l'équipe sont appréciés. Cependant, ce type de changement au cours de cette phase de développement suggère des erreurs de conception fondamentales.
Soyons honnêtes avec nous-mêmes, nous avons tous commis ce genre d'erreurs, il n'y a donc aucune valeur à porter un jugement, mais quand je fais une erreur, cela m'humilie et, espérons-le, me rend plus prudent par la suite. Je n'ai pas l'impression que cela ait le même effet sur l'équipe d'Anagular.

J'aime penser aux déclarations comme "l'astuce" qui m'empêche d'avoir à placer physiquement tous mes composants, directives et canaux dans le même fichier physique (comme vous auriez à le faire avec les modules ES6 si vous vouliez que toutes ces classes soient appartiennent au même module ES6).

Donc, pour moi, les déclarations remplacent le collage de ces fichiers dans un très gros fichier. C'est mon modèle mental de toute façon.

@wardbell Peut-être qu'il me manque quelque chose de fondamental, mais je ne vois pas en quoi l'utilisation NgModule.declarations est fondamentalement différente de l'importation de tous, mais seulement de la réexportation de certains de vos ESModules. Ironiquement, la principale limitation des ESModules est qu'ils ne fournissent que le concept de modules physiques, pas de modules logiques. Je ne vois pas comment NgModule améliore cela. Il s'agit simplement d'une syntaxe d'agrégation différente, mais qui n'élève pas le niveau d'abstraction à un degré significatif.

De plus, les NgModules échouent complètement à résoudre un problème majeur :

L'ensemble du motif Function[] est opaque dans tous les sens. Il laisse tomber la découvrabilité à zéro. Il faut lire la source pour déterminer ce qui se trouve dans un éventail de fournisseurs. Il en va de même pour NgModule.exports .

Mais IMO, mieux vaut expédier le bon produit que de suivre servilement une idée de ce que devrait être un RC et de livrer le mauvais produit. Aussi ... et ce n'est pas très rassurant à dire ... mais si vous avez observé récemment d'autres grands éditeurs de logiciels, vous avez peut-être remarqué une notion tout aussi flexible de "release candidate". C'est la façon dont notre industrie va pour une raison quelconque.

@wardbell La plus grande frustration à propos de RC pour moi est l'impression qu'une version bêta vient d'être poussée vers RC à cause de ng-conf et de google i/o. Pour progresser, la raison doit être claire : c'est le _marketing_ et en tant que technologues, nous devons lutter contre la tendance de ces notions flexibles de maturité. Vous connaissez peut-être un constructeur automobile populaire dans la vallée où la discussion porte sur la question de savoir s'il a été juste de vendre une version bêta pour un produit, car cela peut prendre une vie. Je ne veux pas exagérer, mais en tant que technologues, nous devons dire si c'est ainsi que va notre industrie, car elle va dans la mauvaise direction.

J'aime l'approche ngmodule mais j'ai une question @robwormald :

J'ai un service partagé qui n'a aucun composant, aucune directive et aucun tuyau. Il n'a que des services ( forRoot ) et contient toutes les classes de modèles commerciaux. Le app.module importe ServerApiModule.forRoot() donc les services sont disponibles pour toute l'application. Les modules de fonctionnalités, qui utilisent les services et les classes de modèle métier, doivent-ils importer ce module partagé ? Techniquement, ce n'est pas nécessaire (pas d'erreurs) mais d'un point de vue sémantique, cela aurait du sens (également pas d'erreurs). Que faire de ce genre de modules ? Importez-les ou pas ? Personnellement, j'aime la deuxième possibilité car elle dit "Hé, je suis un module de fonctionnalités et j'ai besoin de ces services et j'ai besoin de ces classes de modèle commercial".

Merci pour une réponse!

Je peux donc ressentir la douleur avec les bibliothèques/bibliothèques d'applications modulaires et ngModule.

Mais comme dit plusieurs fois, ne mélangez pas les deux manières possibles. C'est et ce sera déroutant.

La bonne approche serait donc de déclarer un ngModule pour chaque composant.
Mais comme cela en fait beaucoup plus de codeur de chaudière pour chaque composant, cela ne fonctionne pas non plus à grande échelle.

Donc, n'ajoutez pas un nouveau décorateur appelé ComponentModule qui est plus ou moins sucré pour éviter de déclarer un composant et un module comme le matériau doit le faire.

Par ici ? Si je vois un composant. Je sais que cela DOIT faire partie d'un ngModule. Si j'ai un cas pour que de nombreux composants les regroupent, je PEUX utiliser NgModule. Si je veux juste un composant autonome comme les "anciens composants", j'utilise le ComponentModule et je connais toutes les dépendances et que cela peut être une dépendance de module pour d'autres modules, mais pas une partie d'eux

@nathraQ si la bonne approche consiste à utiliser NgModule pour chaque composant, et c'est peut-être le cas, alors NgModule n'aurait pas dû être introduit et le composant aurait dû être amélioré. En ce qui concerne le passe-partout, Angular 2 est si lourd que cela n'a guère d'importance à ce stade.

De nombreux frameworks qui n'ont pas leur propre système de modules ont utilisé avec succès des conventions pour établir des modèles standard pour la disposition et la visibilité des constructions. Un homme sage a dit un jour qu'on ne peut pas définir les conventions après coup ; qu'ils doivent être là dès le début. J'étais sceptique quant à cette affirmation, mais cette débâcle prouve qu'il avait raison.

@aluanhaddad désolé je ne suis pas d'accord. J'avais mes cas d'utilisation pour un seul module dans angular 1.x avec une gestion des dépendances personnalisée (comme le démarreur de ce fil), mais j'avais aussi des cas d'utilisation de modules pour regrouper un ensemble de contrôleurs, de directives et de services.

Les deux sont utiles. Maintenant, nous devons trouver comment l'intégrer compréhensible pour tout le monde

Wow, c'était long à lire :smile:

Je peux voir les avantages et les inconvénients du nouveau changement, mais cela m'a fait penser à un scénario avec lequel j'ai eu des problèmes dans Angular 1.

@wardbell @robwormald -

Si j'utilise le modèle SharedModule et que j'importe deux bibliothèques tierces (ui-bootsrap vs angular-strap n'importe qui?) Qui utilisent toutes deux le même sélecteur pour un composant, disons my-selectbox

J'obtiendrai une erreur si j'essaierai de les importer tous les deux ? à droite?

Une solution que j'ai lue ici consiste à réexporter l'une des bibliothèques dans un module personnalisé
Mais cela signifie que je dois continuer à mettre à jour le module wrapper à chaque mise à jour de la bibliothèque, non ?

De plus, il peut arriver que j'aie mon propre sélecteur de composants avec le même nom (et dans les gros projets qui peuvent se produire plus d'une fois)

Existe-t-il une solution recommandée à ce problème ? ou est-ce le "module wrapper" ?
(J'espère que nous ne reviendrons pas à l'utilisation d'un préfixe pour les sélecteurs, ce n'était pas amusant)

Merci d'avance!

L'espacement des noms, ou le préfixe comme certains l'appellent, est généralement une bonne idée, quelle que soit la taille de votre projet. Oui, cela peut être plus trivial dans les petits projets, mais dès que des modules tiers sont impliqués, je dirais que c'est presque une exigence - au minimum, cela offre une tranquillité d'esprit en sachant que les collisions ne se produiront pas même si d'autres modules sont mis à jour , mais aussi les développeurs peuvent facilement identifier ce qui appartient à chaque module sans nécessairement avoir à suivre l'arborescence des dépendances.

@nathraQ Tous ces modèles peuvent être réalisés avec les modules ECMAScript. L'introduction de NgModule ne nous mène nulle part et le fait que des bibliothèques comme AngularMaterial transforment les composants en NgModules juste pour préserver l'encapsulation précédemment fournie prouve ce point.

@aluanhaddad NgModules essaie de faire quelque chose de très différent des modules ES et ne remplace pas non plus l'encapsulation des composants, c'est-à-dire que les modules ES et les composants n'ont pas changé leurs responsabilités principales. NgModules est le moyen par lequel vous décrivez l'architecture de votre application, ce qui aide Angular à mieux comprendre votre intention et à optimiser en conséquence, permettant des choses comme compiler certaines parties de votre application à l'avance, servir des modules résolus dynamiquement à partir d'un serveur, etc. qui ne peuvent pas être atteints avec les modules ES. Pour les mêmes raisons, un NgModule par composant n'est pas la règle générale à suivre.

Il est vrai que les applications plus simples peuvent ne pas bénéficier autant de ces avantages, mais dans ces cas, les NgModules devraient de toute façon être moins "gênants".

@emilio-martinez , comme l'a écrit @aluanhaddad , ES6 et "l'ancienne voie angulaire 2" nous ont donné l'espacement de noms dont nous avions besoin.

J'ai travaillé sur de très gros projets avec Angular 1, ayant un sélecteur nommé : mb-product-list peut entrer en collision très rapidement avec d'autres s'il s'agit d'un grand projet (même dans une équipe de plus de 5 développeurs).

En essayant de le résoudre avec plus d'espace de noms, vous vous retrouvez avec : mb-somefeature-product-list , ce qui rend les modèles sales.

J'étais très heureux de voir que cela avait été résolu dans ng2 à cause des métadonnées directives .
Vous pouvez installer npm n'importe quel package de votre choix et n'importer que ce dont vous avez besoin par composant.

ngModules a ses avantages, c'est sûr, il aide à charger des morceaux de manière asynchrone et nous aide également à écrire moins d'importations et améliore la productivité.

Mais l'utilisation du modèle SharedModule introduit un espace de noms global, un peu comme nous l'avions dans ng1.

Au moins avec les fournisseurs, il est nommé par le jeton ES6, l'emplacement du fichier.

Avec les composants, à cause des sélecteurs, ça criera qu'il y a deux composants avec le même sélecteur.

J'aimerais que nous disposions d'un moyen simple de configurer un espace de noms spécial pour les cas d'utilisation de collisions avec des composants tiers ou locaux partagés.

Quelque chose comme "le remplacement du sélecteur".

C'est ce que je demandais

Merci @robwormald pour vos informations détaillées, mais une chose de la part de débutants comme moi (la plupart du temps, je suis un développeur backend). J'apprends Angular 2 et avec tapuscrit. Donc, le concept de module ES6 est un peu flou pour moi
Nous avons une structure d'application complexe. C'est une application d'analyse, où mon nombre de composants est de près de 60.
Et je pense qu'il est bien structuré sous RC4. En dehors de Login, nous n'avons utilisé aucun type de routage, car routern recrée l'ensemble du composant. Nous prévoyons donc une application basée sur un onglet. Deux onglets principaux sont là (1.Analysis 2.Dashboard).
L'onglet Analytics aura plusieurs onglets, chacun ayant une seule analyse en dessous. Le tableau de bord aura également
plusieurs onglets, mais chaque onglet consistera en plusieurs analyses qui ont été enregistrées sous
la section analytique. Donc aller et venir à partir de plusieurs onglets (sous le tableau de bord et l'analyse)
et également en basculant entre l'onglet Tableau de bord et l'onglet Analytics, nous pensons que le routage ne servira pas
notre objectif (corrigez-moi si je dis quelque chose de stupide).
Maintenant, le RC5 NgModule casse notre application. Nous ne savons vraiment pas comment
reconcevoir notre application. Pouvons-nous vraiment utiliser la compilation AoT dans notre application ? N'est-ce pas
tout l'AoT est basé sur le routage ?

@shariez NgModules fournit exactement ce type d'espacement de noms. Essayons de clarifier un peu plus ce point...

L'élément clé à réaliser ici est qu'un composant est compilé, plus ou moins, "à l'intérieur" du module dans lequel il est déclaré - voir https://plnkr.co/edit/9w10b1Y8Bjr5DDIxOwnC?p=preview pour un exemple.

Notez qu'il y a deux sélecteurs en conflit ( my-generic-selector ) - chacun des modules de fonctionnalités importe l'un d'eux, est capable de l'utiliser en interne à ce module, sans polluer les espaces de noms "globaux".

Donc utilisé comme

<my-app>
  <!-- belongs to FeatureModuleOne -->
  <feature-one></feature-one>
  <!-- belongs to FeatureModuleTwo -->
  <feature-two></feature-two>
</my-app>

s'étend à

<my-app>
  <!-- belongs to FeatureModuleOne -->
  <feature-one>
    <!-- the generic imported in FeatureModuleOne -->
     <my-generic-selector></my-generic-selector>
  </feature-one>
  <!-- belongs to FeatureModuleTwo -->
  <feature-two>
    <!-- the generic imported in FeatureModuleTwo -->
    <my-generic-selector></my-generic-selector>
  </feature-two>
</my-app>

sans aucun conflit, car lorsque le compilateur compile feature-one et feature-two, il le fait _dans le contexte du module auquel ils appartiennent_, ce qui évite de polluer une portée globale.

@robwormald Bien sûr, c'est génial et c'est mieux que Angular 1 dans ce sens.

Le cas d'utilisation sur lequel j'ai écrit faisait référence au modèle d'utilisation d'un SharedModule global comme suggéré dans les docs .

Si j'essaie de déclarer à la fois GenericSelectorFeatureOne et GenericSelectorFeatureTwo l'intérieur de SharedModule , j'obtiendrai une erreur, n'est-ce pas ?

Ou si SharedModule a tout un tas de composants communs utiles et que je veux l'importer dans chaque module de fonctionnalité.

Si mon module de fonctionnalités a un sélecteur en collision, ou si un tiers a un sélecteur en collision avec l'une des bibliothèques existantes exportées dans le SharedModule , il émettra une erreur, n'est-ce pas ?

@shairez Je pense que la plupart des applications se retrouveront avec un certain nombre de "SharedModules", et la probabilité de collisions est faible - les modules sont bon marché, il n'y a donc pas un gros coût pour en avoir beaucoup.

Si vous avez des idées sur la façon d'améliorer les docs, un PR serait le bienvenu.

Merci c'est la réponse que je cherchais, je vais tester.

Je n'ai pas encore de meilleures idées sur la façon de résoudre ce problème avec la nouvelle façon d'écrire des modules, c'est pourquoi je l'ai demandé ici, mais une fois que j'aurai testé la solution de plusieurs modules partagés, j'aurai plus de matériel pour en discuter avec @ wardbell et soumettez un PR.

Merci pour l'aide @robwormald !

D'après les dernières documentations disponibles sur https://angular.io , il existe de nombreux avertissements concernant les anti-modèles et les bogues qui peuvent facilement apparaître si NgModule s sont composés de manière incorrecte. Par example

Ne spécifiez pas de fournisseurs de singleton à l'échelle de l'application dans un module partagé. Un module chargé paresseux qui importe ce module partagé créera sa propre copie du service.

C'est plutôt troublant. Si vous suivez l'approche éprouvée de _first make it work, then make it fast_, vous devrez probablement ajuster les modules qui sont chargés avec impatience ou paresseusement en fonction de métriques empiriques et de la structure émergente de ces modules à mesure que votre application ou votre bibliothèque se développe. Fondamentalement, pourquoi un module devrait-il se soucier s'il est chargé paresseusement ou avec impatience ?

Un autre problème, apparemment plus grave, découle de la juxtaposition des sections suivantes des documents

Supposons qu'un module nécessite un HttpBackend personnalisé qui ajoute un en-tête spécial pour toutes les requêtes Http. Si un autre module ailleurs dans l'application personnalise également HttpBackend ou importe simplement le HttpModule, il pourrait remplacer le fournisseur HttpBackend de ce module, perdant l'en-tête spécial. Le serveur rejettera les requêtes http de ce module.
Évitez ce problème en important le HttpModule uniquement dans AppModule, le module racine de l'application.

Puis-je réexporter des cours et des modules ?
Absolument!
Les modules sont un excellent moyen d'agréger de manière sélective des classes d'autres modules et de les réexporter dans un module consolidé et pratique.
Un module peut réexporter des modules entiers qui réexportent effectivement toutes leurs classes exportées. Le BrowserModule d'Angular exporte quelques modules comme celui-ci :
exporte : [ModuleCommun, ModuleApplication]
Un module peut exporter une combinaison de ses propres déclarations, de classes importées sélectionnées et de modules importés.

Ainsi, d'une part, les documents découragent les utilisateurs de réexporter certains modules, tout en indiquant que cela offre une grande commodité.

La notion de réexportations NgModule est analogue à celle des réexportations du module ES, sauf que vous avez moins de contrôle. JavaScript a une portée statique (oui, je sais que this ne l'est pas) et c'est l'une de ses plus grandes forces, permettant une composition extrêmement flexible et le masquage d'informations. JavaScript prend également en charge l'observation afin que vous ayez toujours un moyen de remplacer une portée.

Le plus gros problème cependant est que les exemples dans les directives tournent tous autour de la façon d'importer les modules de framework @angular/*. Ceux-ci sont naturellement divisibles de manière à prévenir intuitivement les conflits. En effet, ils existent pour fournir des services au niveau de l'infrastructure qui ne se chevauchent généralement pas. Les modules définis par l'utilisateur peuvent couvrir de nombreuses couches et peuvent vouloir améliorer ou modifier une variété de comportements. Par exemple, un module de journalisation peut vouloir accéder aux services Router et Http tout en fournissant plusieurs composants pour afficher des informations aux utilisateurs administratifs et utiliser l'un des modules de formulaires pour les définir.

La documentation ne dit rien si les réexportations sont transitives... Le module A réexporte CommonModule. Le module B réexporte le module A. Le module C importe le module B. Cela signifie-t-il que le module C peut désormais utiliser les directives de CommonModule ?

@Martin-Wegner Ils sont transitifs comme décrit ici https://angular.io/docs/ts/latest/cookbook/ngmodule-faq.html#! #q-re-exporter

@aluanhaddad où? Je ne trouve aucun mot sur les réexportations transitives avec plus d'un saut ...

En lisant ce que @aluanhaddad a extrait de la documentation d'angular, j'ai l'impression que je dois reconsidérer tout ce que j'ai appris sur Angular 2 et peut-être même s'il n'y a pas de framework qui gère mieux les dépendances.

Si je comprends bien. Si j'ai un module d'application qui importe HttpModule et que j'ai un module de fonctionnalités avec un service qui utilise le service Http, je ne devrais pas importer HttpModule au niveau du module de fonctionnalités mais au niveau du module d'application. Et si je crée un module de fonctionnalités partagé entre plusieurs modules d'application ? Je dois vraiment importer HttpModule dans le module App. Je ne peux pas dire que mon module de fonctionnalités dépend du HttpModule. C'est vraiment moche et cela signifie que la définition de NgModule manque de nombreuses fonctionnalités comme par exemple PeerDependecies.
Oh mec. On dirait qu'angular 2 se brise. Je crains qu'il ne soit temps de recommencer, d'abandonner angular 2 et de commencer par angular 3.

Il y a tellement de sens dans ce que vous venez de dire. j'ai commencé ça
voyage angular2 depuis l'année dernière et je n'ai eu aucune raison de me sentir battre
malgré tous les changements de rupture que nous avons vus jusqu'à présent (de l'alpha à la bêta,
et RC). C'est compréhensible à ces phases et puisque c'est religieusement coincé
à la philosophie qu'il a utilisée pour me sortir de mes Backbonejs minimalistes.
L'idée même de ce ngModules pour moi s'est avérée quelque peu contraire
productif. Et c'est triste de voir tout le temps que j'ai mis à évangéliser le
la richesse des "composants" minimalistes et sans ballonnements, rendez-vous sur
absolument gaspillé.
Le 29 août 2016 à 9h44, "Daniel Schuba" [email protected] a écrit :

Lire ce que @aluanhaddad https://github.com/aluanhaddad a extrait de
les docs d'angular j'ai l'impression de devoir reconsidérer tout ce que j'ai
appris sur Angular 2 et peut-être même s'il n'y a pas de framework qui
gère mieux les dépendances.

Si je comprends bien. Si j'ai un module d'application qui importe HttpModule et que je
avoir un module de fonctionnalités avec un service, qui utilise le service Http, je ne devrais pas
importez HttpModule au niveau du module de fonctionnalité mais au niveau du module d'application. Et alors
si je crée un module de fonctionnalités partagé entre plusieurs modules d'application ? j'ai
vraiment sur HttpModule étant importé dans le module d'application. je ne peux pas dire,
que mon Feature Module dépend du HttpModule. C'est vraiment moche et
signifie que la définition de NgModule manque de nombreuses fonctionnalités comme par exemple
PeerDependecies.
Oh mec. On dirait qu'angular 2 se brise. Je crains qu'il soit temps de
recommencer, abandonner angulaire 2 et commencer avec angulaire 3.


Vous recevez ceci parce que vous êtes abonné à ce fil.
Répondez directement à cet e-mail, consultez-le sur GitHub
https://github.com/angular/angular/issues/10552#issuecomment -243066961,
ou couper le fil
https://github.com/notifications/unsubscribe-auth/AF675h8_np9i5cHgL8mMOOu8vMMQmWKkks5qkpv8gaJpZM4Jee-o
.

Quelqu'un pourrait-il me corriger si je me trompe.

Je pense organiser une application comme suit.

application
|--Droit/
|----De nombreux composants.
|----LawNGModule.
|--Utilisateur/
|----De nombreux composants
|----UserNGModule
|--AppNGModule
|--SomeFirstLeveComponents

Disons que je veux travailler avec Angular Material. Avant, je détestais un peu le fait que j'avais trop de plaque de chaudière important chaque élément dans chaque composant. Maintenant, je l'ajouterais au module NG. Mais depuis que j'ai décidé d'utiliser un module ng par fonctionnalité, je dois faire les importations pour chaque module ng que je considère. Pas seulement la racine. Est-ce correct?

Ou peut-être s'agit-il d'un cas où vous créez un module x pour réexporter y(Material) un autre module, et vous l'importez dans les modules dont vous avez besoin ?

@ReneVallecillo Vous avez raison. Vous devez l'importer dans chaque module de fonctionnalité. Ou vous l'ajoutez avec d'autres modules dans un module partagé (cachant la dépendance), qui le réexporte et utilise ensuite ce module partagé. Et si vous le réexportez dans un autre module, vous pourriez même avoir des importations en double sans le savoir et le voir immédiatement.

@robwormald En réponse à votre commentaire ci-dessus :

En mode AoT cependant, cela fonctionne un peu différemment - au moment de la construction, nous extrayons statiquement (c'est-à-dire sans exécuter votre code) les mêmes métadonnées du code source en recherchant des décorateurs.

Cela signifie-t-il que vous extrayez statiquement des modules du code source d'origine, et qu'en tant que tel, nous ne pouvons effectivement pas créer de modules dynamiquement ?

Afin de faciliter la migration, je pensais créer une fonction qui créerait des modules dynamiquement; quelque chose comme ça:

function createModule (entryComponent: Type, dependencies: Type[]) {
    @NgModule({
        imports: [CommonModule, FormsModule],
        declarations: [entryComponent, ...dependencies],
        exports: [entyComponent]
    })
    class FeatureComponent {}
    return FeatureComponent;
}

Donc, même si cela (probablement ?) Fonctionnerait avec la compilation JIT, cela ne fonctionnerait pas avec AoT car AoT analyse statiquement le code source, à la recherche de décorateurs ?

Cette complexité inutile à l'ère de l' ES@next.... @aluanhaddad fait de très bons points.

Dans l'état actuel des choses, je ne peux pas me voir / mon équipe aller de l'avant avec Angular 2 si telle est la direction prévue. Et il semble que ce soit le cas, car cela a été "fermé".

Je devrai peut-être faire comme @DaSchTour et rechercher d'autres frameworks frontaux. Dommage, car il y a quelques mois, NG2 était une vraie joie de travailler avec et mon choix évident de la portée.

@iyobo mis à part la douleur initiale du changement, la _vaste_ majorité (et je parle à un _lot_ de développeurs) des commentaires sur NgModules a été positif.

Considérés isolément dans une application hello world, vous pourriez argumenter sur son "complexe" ("inutile" est factuellement incorrect, selon l'explication ci-dessus), mais ils prennent vraiment tout leur sens dans une application réelle - organisation des fonctionnalités, routage paresseux et Les AoT sont tous rendus tellement plus simples avec NgModules. Étant donné le choix aujourd'hui, j'opterais toujours pour l'ajout de NgModules dans le framework.

Je suis avec @robwormald ici, la douleur initiale de la migration de RC4/5 vers NgModules était gérable après avoir vu les avantages de ne pas avoir à importer chaque composant/tuyau dans une page nouvellement créée.
Les NgModules commencent à briller après être devenus un peu plus complexes et avoir beaucoup de composants partagés.

Il est tellement plus facile d'importer SharedModule et d'en finir.

Hey @robwormald , L'idée que l'on n'est pas d'accord avec la direction actuelle de Ng2 n'est en aucun cas une affirmation factuelle selon laquelle ils ne fonctionnent que sur les applications de niveau "hello world".

Ce "cloisonnement des fonctionnalités" dont vous parlez n'est pas nouveau. C'est quelque chose qui a toujours été conçu selon les besoins pour s'adapter à chaque produit/solution individuel utilisant des composants.
Cela dit, il n'y a toujours pas de plus grande compartimentation qu'un composant déclarant ce dont il a besoin par lui-même.

Maintenant, en ce qui concerne le chargement paresseux, reculer et regarder les choses à vol d'oiseau, le principal avantage du chargement paresseux est d'améliorer la vitesse de chargement de l'application. Je pense que la majorité d'entre nous ont des pipelines qui font que cela fonctionne. Entrez la minification, la compression et plusieurs points d'entrée d'application sous forme de pack Web.

Il me semble simplement que NgModules est une solution à la recherche d'un problème, plutôt qu'une solution à un problème réel. Mais encore une fois, je ne peux pas prétendre tout savoir...

Je pense que le temps montrera si l'introduction de NgModules était une bonne idée. J'ai l'impression qu'Angular 2 n'est actuellement fait que pour atteindre certains objectifs de conception. Personne n'a pensé à des choses comme des équipes avec des niveaux de compétences différents, un code qui vieillit et qui est transmis à des générations de développeurs. Dans un monde idéal, cela peut sembler une excellente idée. Mais en réalité, NgModules introduit beaucoup de pièges et d'obscurcissements qui causeront beaucoup de problèmes dans la phase de formation et d'introduction dans un nouveau projet. Ce n'est tout simplement pas aussi simple et intuitif qu'avec la déclaration au niveau du composant. Les dépendances sont cachées dans les modules et ce n'est qu'une question de temps pour commencer à rechercher le module dans lequel se trouve votre composant.

Ayant récemment effectué la transition d'une application plus large vers NgModules, je pense qu'ils sont pour la plupart une bonne chose (maintenant que j'en ai terminé, cela a du sens). Je pense en fait que le problème majeur est qu'ils nécessitent une structure de composants différente, quelque chose qui ne correspondait probablement pas bien à la façon dont vous avez structuré votre application auparavant (du moins c'était le cas pour moi).

Cependant, j'ai l'impression qu'ils ne devraient pas exister comme la seule solution. Si vous regardez comment les composants sont très souvent construits, vous réalisez que très souvent, ils sont composés de sous-composants plus petits et hautement spécialisés. Pour ces sous-composants, qui n'ont aucun but en dehors de ce composant de conteneur, devoir les maintenir dans le module de portée supérieure est vraiment fastidieux et peut rapidement entraîner des problèmes de portée.

J'apprécierais vraiment s'il y avait un mécanisme _en plus_ de NgModules qui permettait aux composants de définir d'autres composants ou directives en tant que dépendances à portée locale qui ne s'appliquent qu'au sein de ce composant exact (tout comme la façon dont la liste directives fonctionnait avant les modules).

J'aime la suggestion de @poke d'avoir une alternative pour ceux qui préfèrent ne pas utiliser les NgModules complets.

NgModules ont été ajoutés dans RC5 pour résoudre les problèmes de fonctionnement de la compilation et du chargement paresseux - ils ne font donc guère partie du plan directeur d'origine, c'est pourquoi ils ne conviennent pas parfaitement à certains cas d'utilisation (surtout si vous construisiez une application basée sur la conception originale "les composants sont rois").

Bien sûr, ils corrigent ou activent certaines choses, mais entraînent également leurs propres complications - plus de choses à apprendre et à concevoir, ce qui est particulièrement difficile lorsque toutes les meilleures pratiques et approches n'ont pas encore été élaborées. L'adoption précoce peut apporter beaucoup de douleur, j'ai appris cela lors du trajet vers RC4.

J'aimais davantage le plan original centré sur les composants, ce qui explique probablement pourquoi je trouve que les composants polymères / Web sont mieux adaptés maintenant. Les modules ressemblent à un demi-pas vers Angular 1.

Au début, j'étais réticent à ce changement de suppression des tuyaux et des directives, mais je m'y suis habitué maintenant et cela ne semble pas aussi grave que je le pensais au départ.

Quelqu'un peut-il me montrer comment NgModules fonctionne dans une application vraiment complexe où plusieurs composants nécessitent plusieurs autres à plusieurs niveaux ? Tous les tutoriels, exemples et dépôts que j'ai vus ne montrent que les moyens simples par lesquels un module encapsule ses propres éléments et publie (exporte) certains d'entre eux vers d'autres.

Dans les projets réels, il existe de nombreuses dépendances inter-requises, généralement avec une chaîne hiérarchique. C'est en quelque sorte faux de prouver un concept de quelque chose par un exemple désigné exactement pour cela.

@pour tous les auteurs d'Angular2 : pouvez-vous s'il vous plaît nous dire honnêtement quelles sont les parties négatives de NgModules ? Je sais que vous pouvez écrire un livre sur toutes les bonnes choses. C'est bon. Mais je dois toujours faire face aux mauvaises choses cachées qui ne seraient pas claires si vous n'en parliez pas.

Quelqu'un peut-il me montrer comment NgModules fonctionne dans une application vraiment complexe où plusieurs composants nécessitent plusieurs autres à plusieurs niveaux ?

Une façon de faire serait de créer un module de dépendance juste pour ces composants : supposons que vous ayez trois ensembles de composants A , B et C qui contiennent plusieurs composants chaque ensemble a ceux qui sont quelque peu liés. Ces trois ensembles fonctionneraient donc bien pour trois modules distincts.

Désormais, les composants de chacun de ces ensembles nécessitent plusieurs composants d'un ensemble D . Ces composants dans D ne sont utilisés que pour les composants de ces trois ensembles. Puisqu'ils sont utilisés dans chacun d'eux, vous ne pouvez pas simplement ajouter les composants à ces modules (puisque les composants ne peuvent faire partie que d'un seul module). À ce stade, vous pouvez fusionner A , B , C et D dans un module gigantesque, de sorte que toutes les dépendances sont là. Mais c'est bien sûr très désordonné. Au lieu de cela, vous créez simplement un nouveau module pour D qui ne contient que ces dépendances. Ce module ne fait rien d'autre que fournir l'accès à ces modulesw. Vous pouvez maintenant importer ce module dans chacun de ces trois autres modules et utiliser les composants. Mais parce que les composants sont toujours "privés", vous ne réexportez pas le module ou n'importez pas le module D dans un autre module.

Étant donné que les importations de modules n'affectent que le module lui-même, cela permet une sorte de portée sans polluer les autres modules. Bien sûr, cela vous oblige à créer plus de modules, mais c'est comme ça que ça marche.

Je peux partager ma configuration actuelle. J'ai utilisé 3 modules dans l'application : CommonModule, AppModule et TestModule.

  • CommonModule importe et exporte les éléments les plus courants tels que HttpModule, FormsModule, MdInputModule, etc.
  • AppModule importe BrowserModule, CommonModule, app.routing et des composants individuels
  • TestModule importe et exporte BaseModule, mais écrase certains fournisseurs, comme XHRBackend avec MockBackend

J'ai introduit cette configuration pour simplifier TestBed.configureTestingModule,
de sorte que je dois importer TestModule puis un seul composant comme:

TestBed.configureTestingModule({
  imports: [ TestModule ],
  declarations: [ MyFormComponent ]
});

Un inconvénient supplémentaire qui est devenu flagrant lorsque j'ai migré de RC-4 vers la version était que les NgModules imposent une lourde pénalité pour les refactorisations simples où un composant doit simplement être divisé. Avec NgModules, vous devez modifier le module conteneur, qui peut être à plusieurs niveaux dans l'arborescence conceptuelle des composants, ou promouvoir le composant en l'enveloppant dans un NgModule, puis en le supprimant de son NgModule parent. La refactorisation des composants est essentielle.

Ceci est directement lié au point de @poke

J'apprécierais vraiment s'il y avait un mécanisme en plus de NgModules qui permettait aux composants de définir d'autres composants ou directives en tant que dépendances à portée locale qui ne s'appliquent qu'au sein de ce composant exact (tout comme la façon dont la liste des directives fonctionnait avant les modules).

Je suis fortement en désaccord. Une architecture modulaire telle qu'elle est proposée par Angular 2 est plus facile à mettre à l'échelle, à ajuster et à refactoriser si nécessaire. Bien sûr, de RC4 à RC5, il y a eu un peu d'ajustement, mais pour moi, les NgModules ont prouvé qu'ils permettaient une application beaucoup plus flexible.

Angular est opiniâtre et ce n'est certainement pas une taille unique, mais NgModules n'est tout aussi certainement pas le point d'échec pour concevoir une application intelligente, moderne et hautement performante.

@emilio-martinez: À mon avis, NgModule ne serait jamais introduit si Angular 2 n'était pas si lent au démarrage, lorsqu'il impliquait JiT. Toutes les autres "améliorations" telles que "la mise à l'échelle, l'ajustement et la refactorisation" sont discutables, comme le montre cette discussion.

Cela fait un bon moment maintenant et beaucoup d'entre nous ont eu le temps d'absorber pleinement NgModule dans notre travail. Je pense qu'il est maintenant clair que, comme bon nombre de personnes l'ont décrit, une fois que vous avez dépassé le ralentisseur du passage au nouveau système de modules, cela permet de très belles choses. Pour tous ceux qui parcourent ce fil ayant du mal à absorber NgModule, je suggère de faire défiler tout le long et de tout lire de @robwormald et @wardbell en particulier.

Je pense que nous découvrirons tous dans un an que de nombreuses applications Angular 2+ utilisent de manière omniprésente et transparente les modules, le chargement paresseux et l'AOT. Je pense qu'il sera complètement routinier pour la plupart ou presque toutes les applications d'utiliser ces éléments pour implémenter la vision "d'application progressive" où même les grandes applications complexes ont un temps de chargement initial presque instantané, puis chargent paresseusement (ou préchargent paresseusement avec optimisme) la fonctionnalité qu'elles avoir besoin. Le résultat est en fait assez étonnamment lisse et obtenu à un coût remarquablement bas pour le développeur d'applications individuel : NgModule est essentiellement ce coût, et c'est une transition irritante mais seulement une quantité très modeste de travail en cours à utiliser.

@kylecordes J'espère que tu as raison et je pense que c'est la bonne attitude à avoir.

@iurii-kyrylenko c'est très vrai.

J'ai un problème avec la compilation angulaire de mon JavaScript car il est supposé que TypeScript compile mon JavaScript, mais c'est un problème distinct.

@kylecordes Je pense qu'il y a beaucoup plus à considérer que la simple transition. Les modules introduisent beaucoup de complexité et de nombreuses possibilités supplémentaires pour ajouter des bogues à la propre application. Le plus gros problème est l'obscurcissement des dépendances. Ce qui causera beaucoup de problèmes dans les prochaines années de développement avec angular 2.

@aluanhaddad Je crois qu'Angular utilise un wrapper tsc pour compiler. C'est bien parce que vous pouvez même l'implémenter dans un workflow de gestionnaire de tâches, par exemple.

La vitesse d'amorçage de @iurii-kyrylenko est également difficile à déterminer sur la base de RC4. Une grande partie du travail qui a été effectué depuis la version finale a été du nettoyage et des optimisations. D'après mon expérience, le JIT compilé par Angular s'exécute plus rapidement que RC4 de toute façon.

@DaSchTour pouvez-vous élaborer sur les bogues que vous avez trouvés en travaillant avec NgModule ?

@emilio-martinez ce ne sont pas des bogues dans NgModule mais des bogues qui surviendront à cause d'importations manquantes ou d'instances de service en double qui auraient été omises ou trouvées à un stade antérieur de développement. Il s'agit d'importer des choses à l'endroit où je les utilise et non à un endroit où je ne vois pas si elles sont nécessaires ou utilisées et à quel endroit elles sont nécessaires et utilisées.

Pensez simplement à TypeScript fonctionnant de cette façon. J'ai un fichier de base pour mon module, appelons-le _index.ts_ il ressemble à ceci.

import {foo} from bar;
import {StartComp} from start;

StartComp.boot();

Ensuite, nous avons un fichier appelé start.ts qui ressemble à ceci.

export class StartComp {
   public static boot() {
      foo()
   }
}

C'est ce que fait Angular avec NgModules. Avec un peu de magie, j'ai importé quelque chose dans un module et il apparaît à l'autre bout de mon application. Vous devez savoir que foo est importé dans index.ts et en exécutant StartComp à partir de l'index, les importations peuvent être utilisées dans le composant.

Les dépendances sont cachées et nécessitent une enquête supplémentaire pour les trouver.

@emilio-martinez

D'après mon expérience, le JIT compilé par Angular s'exécute plus rapidement que RC4 de toute façon.

J'ai un projet de complexité moyenne, basé sur MEAN stack et Angular 2 final. Il faut environ 10 secondes pour terminer le démarrage en mode JIT sur mon appareil Android. Je considère cela comme un retard important. Actuellement, je ne peux pas utiliser la compilation AOT sans modifier mon code source (problèmes avec les membres privés, opérateur elvis ...).

Quelqu'un a-t-il des informations sur les performances AOT + chargement paresseux pour des projets réels ?

Je crois qu'Angular utilise un wrapper tsc pour compiler. C'est bien parce que vous pouvez même l'implémenter dans un workflow de gestionnaire de tâches, par exemple.

@emilio-martinez c'est exactement ce que je ne veux pas. Je veux compiler mon code en utilisant la version de TypeScript que je veux, par exemple 2.1.0-dev qui a une émission de niveau inférieur pour async/wait. Je ne veux pas qu'Angular se charge de compiler mes fichiers TypeScript, cela ne doit pas être délégué à un framework, c'est le rôle d'un langage. Sans m'éloigner du sujet, je n'aurais pas touché @Script avec une perche de dix pieds, Dieu merci, c'est mort.
En ce qui concerne le flux de travail, j'utilise JSPM et parfois Webpack, pas un gestionnaire de tâches traditionnel, et je laisse mon IDE gérer mes linters.

Un autre problème est que j'ai écrit des décorateurs abstraits sur des décorateurs angulaires et je comprends maintenant que beaucoup ne les ignorera pas. Compte tenu de la lourdeur angulaire des décorateurs, j'ai été très déçu d'apprendre que le framework ne prendrait pas entièrement en charge les décorateurs, les traitant, pendant AOT, comme des annotations statiques alors qu'ils sont en fait une construction d'exécution dans le langage sous-jacent.

@aluanhaddad il est important de comprendre qu'il y a deux étapes distinctes lors de la compilation AoT - la première génère un _nouveau_ code dactylographié, la seconde transpile ce code vers ES5/6. ngc fait les deux par commodité, mais il n'y a rien d'inhérent à AoT qui l'exige. À l'intérieur de Google, nous faisons les deux, et donc ce cas est la priorité. N'importe qui pouvait implémenter un hôte de compilateur pour prendre en charge la génération de code dans n'importe quel environnement de son choix.

Nous ne prenons pas (encore) en charge l'abstraction en plus des décorateurs intégrés angulaires, mais si vous vouliez utiliser quelque chose comme https://www.npmjs.com/package/core-decorators , ce serait bien.

@iurii-kyrylenko vous suggère de regarder le discours d'ouverture du premier jour d'AngularConnect, où LucidCharts a parlé de son expérience avec AoT. Voir https://youtu.be/xQdV7q3e_2w?t=1411

À mon humble avis - l'objectif n ° 1 de tout le monde devrait être d'obtenir la compilation AoT dès que possible. La performance est tout simplement imbattable.

@robwormald Je n'ai pas regardé quelles options sont disponibles lors de l'appel ngc - donc cela pourrait déjà être couvert. Je pense que ces options pourraient apaiser les inquiétudes comme celles exprimées ici, si elles montrent clairement que NGC remplit le premier objectif comme sa principale raison d'exister dans le second objectif en tant que commodité/optimisation. Si la documentation ou l'aide montre comment exécuter séparément tsc pour ceux qui préfèrent le faire, cela pourrait encore apaiser les inquiétudes ?

@kylecordes , je ne pense pas que la documentation expliquera comment implémenter votre propre hôte de compilateur de si tôt. C'est un cas d'utilisation avancé, et nécessiterait donc un apprentissage autonome à mettre en œuvre. Nous avons implémenté une chose similaire pour la CLI ici https://github.com/angular/angular-cli/tree/master/packages/webpack

@robwormald Ah, je ne veux pas dire implémenter votre propre hôte de compilation. Je voulais juste dire un "processus de construction" de deux lignes - d'abord en appelant ngc pour émettre du texte généré, puis en appelant vous-même tsc pour compiler tout le texte (votre source plus la source générée) pour JavaScript. Cela fournit une assurance rapide que le code tapuscrit est simplement compilé en JS par le compilateur de tapuscrit standard.

@robwormald Merci pour votre réponse.
En ce qui concerne NGC, ce que je veux savoir, c'est si je peux contrôler la version et les paramètres du compilateur TypeScript dans la passe TS -> TS . Puis-je transmettre TypeScript à NGC ou dois-je utiliser une version spécifique qui encapsule une version spécifique de TypeScript ? À quel point sont-ils couplés ?

En ce qui concerne les décorateurs, existe-t-il une prise en charge du suivi des problèmes pour les décorateurs définis par l'utilisateur qui font abstraction des décorateurs angulaires ? Le https://www.npmjs.com/package/core-decorators est un ensemble orthogonal de décorateurs, mais j'ai des décorateurs qui appliquent des modèles et des conventions dans mes applications angulaires en enveloppant des décorateurs angulaires. Un cas d'utilisation évident pour cela est de créer et d'appliquer automatiquement des préfixes de nom de composant à l'échelle du package, mais il en existe d'autres également.

Puisque NGC ne le supporte pas, comment sait-il quels décorateurs sont spécifiques à Angular ?
Correspond-il aux décorateurs angulaires par leur nom ?
J'espère que non, car cela violerait la portée lexicale de JavaScript.
Un scénario simple
_awesome-component-decorators.ts_

import { Component } from '@angular/core';
import template from './awesome-component.html';
import style from './awesome-component.less';

export const awesomeComponet = <T extends new (...args) => any>(target: T) =>
  Component({template, styles: [style], selector: snakeCase(target.name) })(target);

_consommateur.ts_

import { awesomeComponet } 'app/shared/awesome-component-decorators';

<strong i="19">@awesomeComponent</strong> 
export class AnAwesomeComponent { }

<strong i="20">@awesomeComponent</strong> 
export class AnotherAwesomeComponent { }

@jpsfs Avez-vous trouvé une solution pour charger dynamiquement les composants sans ajouter de déclarations de composants au module d'application racine ? .

Je fais également partie d'un projet de migration angular 1.X vers Angular 4. Ce projet comporte un grand nombre de composants qui sont réutilisés dans différentes applications qui sont chargées paresseusement en fonction du contexte de l'application.

Selon ma compréhension dans Angular 4

Nous devons ajouter des dépendances de composants dans les déclarations root @NgModule comme ci-dessous.

importer {platformBrowserDynamic} de "@angular/platform-browser-dynamic" ;
importer {Composant, NgModule} de "@angular/core" ;
...
...
@NgModule({
importations : [BrowserModule], // importe le BrowserModule d'Angular
bootstrap: [BootStrapComp], // indique le composant bootstrap
déclarations : [com1, comp2 , comp5 ...... Comp n ] // enregistre notre composant avec le module
})
classe d'exportation AppModule {}

platformBrowserDynamic().bootstrapModule(AppModule);

Mais dans notre cas, nous ne voulions pas rooter NgModule pour connaître les dépendances des composants au moment de la compilation. Nous voulions plutôt que les composants soient chargés dynamiquement au moment de l'exécution.
Avez-vous trouvé de bonnes solutions qui peuvent amorcer l'application sans ajouter tous les composants dans les déclarations NgModule racine (et nous ne voulions pas non plus avoir un NgModule pour chaque composant :) )

@DaSchTour

Vous souvenez-vous des moments où votre point d'entrée d'application ressemblait à ceci ?

Eh bien, pour cela, certains d'entre nous ont utilisé des scripts de construction pour exiger automatiquement ces modules et les ajouter au module d'application.

Je cherche quelque chose de similaire et de solution simple dans angular2.

@samudrak , vous ne pouvez pas charger paresseux uniquement le composant si vous souhaitez utiliser le support Angular aot. Vous devrez configurer le module paresseux pour chaque composant et charger paresseux le module. Nous utilisons une approche similaire dans notre application...

Avec la prise en charge des importations dynamiques dans ECMAScript et maintenant dans TypeScript (avec une vérification de type complète orthogonale au chargement), le cas d'utilisation du chargement paresseux est assez arbitraire. Bien sûr, le recul est de 20/20 et il n'y avait aucun moyen de savoir que cela arriverait.

Ce problème a été automatiquement verrouillé en raison de son inactivité.
Veuillez signaler un nouveau problème si vous rencontrez un problème similaire ou connexe.

En savoir plus sur notre politique de verrouillage automatique des conversations .

_Cette action a été effectuée automatiquement par un bot._

Cette page vous a été utile?
0 / 5 - 0 notes