Angular: NgModule für große Projekte

Erstellt am 7. Aug. 2016  ·  144Kommentare  ·  Quelle: angular/angular

Ich sende ein ... (mit "x" ankreuzen)

[X] feature request / proposal

Ich habe über NgModule gelesen und möchte einige Anwendungsfälle darlegen, bei denen ich nicht ganz sicher bin, ob der aktuelle Vorschlag (https://docs.google.com/document/d/1isijHlib4fnukj-UxX5X1eWdUar6UkiGKPDFlOuNy1U/pub) berücksichtigt .

Kontext

Ich bin Teil eines Teams, das ein Enterprise Framework (basierend auf Angular 2) erstellt. Dieses Framework wird dann die Basis für andere Apps innerhalb desselben Ökosystems sein.

Wir haben das Framework in kleinere Projekte/Module unterteilt (stellen Sie sich diese als getrennte npm-Pakete vor). Diese Module sind Sätze von Steuerelementen (die dann in anderen Modulen wiederverwendet werden) oder Seiten, die diese Steuerelemente verwenden.

Beispiel

Ein kurzes Beispiel kann sein:

Steuerungsmodul

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

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

}

Checklisten-Modul
// Das Checklistenmodul hängt vom Kontrollmodul ab. Controls wird als Modul eines Drittanbieters behandelt.

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 kennt weder Controls- noch Checklist-Module. Sie werden abhängig von der Interaktion des Benutzers verzögert geladen. Wenn der Benutzer in diesem Fall zu einer Checklist navigiert, wird die ChecklistPage-Komponente geladen und dann folgt auch die MyComboBox (wegen des _Imports_ von ChecklistPage)

Das Checklistenmodul hat weitere Dutzend Komponenten. Jeweils abhängig von anderen Dutzend Komponenten aus mehreren Modulen.

Es ist unpraktisch (um nicht zu sagen fast unmöglich), alle Komponenten in die NgModule-Deklaration importieren zu lassen. Wir sprechen von mehreren hundert Komponenten, die während der App-Laufzeit _möglicherweise_ verwendet werden.

Außerdem muss die Anwendung möglichst modular und lazy load sein. Unterschiedliche Interaktionen innerhalb der App führen dazu, dass völlig unterschiedliche Module geladen werden.

Erwartetes/erwünschtes Verhalten

Die aktuelle Lösung mit komponentenbezogenen Richtlinien funktioniert für diesen Anwendungsfall wie ein Zauber. Nicht sicher, wie dies mit NgModule ablaufen wird.

Darüber hinaus können wir derzeit die von jeder Komponente (in diesem Fall ChecklistPage) benötigten Abhängigkeiten klar erkennen. So wird die Wartung viel einfacher.

Es scheint eine fantastische Lösung für kleine Anwendungen zu sein, alle benötigten Komponenten in ein NgModule zu importieren und sie dann undeutlich auf mehreren Komponenten zu verwenden. Ich denke, dass es bei einer langfristigen Entwicklung, mit mehreren Iterationen über mehrere Jahre, mit Teamrotation, ... großartig ist, jede Komponente explizit anzugeben, wovon sie abhängt, ohne in die Vorlage zu schauen (und Kompilierungsfehler zu haben, wenn etwas fehlt). Vorteil.

Fazit

Bitte lassen Sie mich wissen, ob ich mich in meiner Erklärung klar ausgedrückt habe. Das Ziel dieser Ausgabe ist es, das Bewusstsein für diese Situation zu schärfen und von Ihnen Feedback zum weiteren Vorgehen zu erhalten.

Wir stehen Ihnen zur Verfügung, um Ihnen unsere aktuelle Arbeit zu zeigen, wir haben mehrere hundert Angular 2-Komponenten in 8 Projekten, die im letzten Jahr (seit Alpha 27) entwickelt wurden.

Hilfreichster Kommentar

Vielen Dank für das Feedback an alle. Entschuldigen Sie, dass es so lange gedauert hat, bis Sie eine Antwort erhalten haben. Wir waren in der letzten Woche sehr beschäftigt (Migration interner Google-Apps auf NgModules, daher spüren wir auch den Refactoring-Schmerz).

Lassen Sie mich sehen, ob ich einige der Fragen und Missverständnisse hier klären kann.

Das Erste, was man über @NgModule() (und @Component und jeden anderen Angukar-Dekorator) verstehen muss, ist, dass sie ein reines Kompilierzeitkonstrukt sind – sie existieren, damit der eckige Compiler einen Abhängigkeitsgraphen in einer Anwendung entdecken kann.

Eine (vereinfachte) Version dessen, was unsere Dekorateure tun, sieht so aus:

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

Sie ändern oder modifizieren das Verhalten der dekorierten Klasse in keiner Weise – sie hängen einfach einige Metadaten an. Angular verwendet diese Metadaten, um Ihre Anwendung zu erstellen und Vorlagen zu kompilieren.

Im JiT-Modus geschieht dies „Just in Time“ – zwischen dem Aufruf von bootstrapModule und dem Rendern der ersten Komponente ruft der Compiler von Angular die an Klassen angehängten Metadaten mithilfe der Reflect-API ab:

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

Im AoT-Modus funktioniert dies jedoch etwas anders – zur Build-Zeit extrahieren wir _statisch_ (d. h. ohne Ausführung Ihres Codes) dieselben Metadaten aus dem Quellcode, indem wir nach Decorators suchen.

Dies funktioniert gut, wenn Sie eine einzelne Komponente booten, aber wir haben viel Feedback von Entwicklern gehört, die komplexere Dinge tun – Bootstrapping mehrerer Root-Komponenten oder Bootstrapping verschiedener Komponenten basierend auf dem Authentifizierungsstatus usw.

Während @Component decorators uns also die Möglichkeit gab, eine Komponente statisch zu analysieren, hatten wir nicht die Möglichkeit, eine _Application_ zuverlässig statisch zu analysieren.

Dinge, die unter den Begriff „Bewerbung“ fallen

  • PLATFORM_DIRECTIVES/PIPES/PROVIDERS
  • Dinge, die Sie zuvor zu Bootstrap() hinzugefügt haben
  • Einstellungen auf Compilerebene
  • mehrere Root-Komponenten
  • serverseitige Nutzung.

NgModules führen die Idee eines statisch analysierbaren Satzes von Merkmalen ein. Interessant ist, dass wir im AoT-Kompilierungsmodus Ihr Root-Modul analysieren und für jedes Modul in der Anwendung eine ModuleFactory _generieren_ - dies ist die vorkompilierte Version eines Moduls, das _nur_ die Factorys enthält, auf die Sie statisch in Templates verweisen, und diejenigen, die Sie selbst als "entryComponents" markieren

Da wir die für die Kompilierung erforderlichen Informationen bereits im Voraus extrahiert haben, können wir die Dekorateure tatsächlich aus dem Baum schütteln (ngc erledigt dies automatisch für das Finale) – und anstatt Ihre Anwendung zu bündeln, beginnend mit Ihrem Root-Modul, beginnen Sie in Ihrer generierten Root Module_Factory_, die nur den Code enthält, der tatsächlich in Ihrer Anwendung verwendet wird, sodass Sie keine Strafe für Modularität zahlen und Tools wie Rollup und Webpack2 effizienter arbeiten können

mehr folgt in der nächsten Antwort...

Alle 144 Kommentare

Es scheint mir nicht, dass ngModules das von Ihnen angestrebte Setup verbietet, haben Sie schon damit gespielt? Sie können mehrere verschiedene Module haben und Lazy Loading usw. durchführen. http://plnkr.co/edit/NAtRQJBy50R19QAl90jg?p=info

Behalten Sie für etwas Ähnliches, was Sie zu tun scheinen, den Übergang von Material2 im Auge: https://github.com/angular/material2/pull/950/files

Hallo @qdouble ,

Danke für die schnelle Antwort.
Wenn Sie sich https://github.com/jelbourn/material2/blob/ecbb4f42e0473899f6ad15d8e4ed8f262ded7a99/src/components/button-toggle/button-toggle.ts ansehen , sagen Sie, dass wir brauchen, um die gleiche Funktionalität zu erreichen, die wir jetzt haben ein NgModule für jede Komponente deklarieren? (Das wurde am Ende der Datei hinzugefügt, oder?)

Außerdem deckt es nicht das Wartungsproblem ab, das ich in meiner ursprünglichen Erklärung erwähnt habe. Die Deklaration der Abhängigkeiten jeder Komponente/Direktive auf ihrem Decorator ist für mich ein großer Vorteil, den ich gerne behalten würde.

@jpsfs Wenn Sie für jede einzelne Komponente einen individuellen Bereich erstellen möchten, müssen Sie vermutlich für jede Komponente unterschiedliche ngModule erstellen. Während dies in Ihrem Fall möglicherweise mehr Code erstellt, wird es wahrscheinlich weniger Code für die überwiegende Mehrheit der anderen Personen erstellen, indem mein Modul statt pro Komponente festgelegt wird.

Was das zweite Problem angeht, könnten Sie das ngModule und die Komponente direkt nebeneinander deklarieren, so dass es zwar 3 oder 4 zusätzliche Codezeilen zu Ihren Dateien hinzufügen würde, aber ich glaube nicht, dass es ein großes Problem verursacht.

Ich würde sagen, die überwiegende Mehrheit der Anwendungsfälle erfordert keine bereichsbezogenen Anweisungen pro Komponente, aber falls dies der Fall ist, unterstützt ngModules dies immer noch für ein paar weitere Codezeilen.

@qdouble Danke.

Ich bin mir nicht sicher, ob dies eine oder/oder-Situation ist, ich kann sehen, dass beide Szenarien zusammenarbeiten, ohne dass die Funktionalität, die wir bereits haben, entfernt werden muss. Wenn jemand Module verwenden möchte, kann ich das als eine großartige Ergänzung sehen. Inzwischen könnte das Framework ohne Module funktionieren (so wie es heute funktioniert). Ich glaube, dass sogar das Offline-Kompilierungsproblem mit den Dingen, wie sie derzeit sind, gelöst werden kann.

Ich lasse dies offen, um zu sehen, ob jemand der Sache etwas hinzuzufügen hat.

@jpsfs verstanden, wenn ich in deiner Situation wäre, wäre es mir definitiv lieber, wenn sie beide Optionen offen ließen :)

Sie haben den Grund für das Verwerfen von Komponentendirektiven in das von Ihnen gepostete Dokument geschrieben, soweit es zwei Bereiche erstellt, und sie denken, dass der ngModule-Bereich klein genug ist und eher dem ES6-Modell entspricht.

Ein Teammitglied erwähnte auch zuvor, dass es im Allgemeinen problematisch ist, Dinge auf zwei verschiedene Arten zu tun ... und langfristig könnte ich das Problem hier sehen ... wenn Sie einige Projekte haben, in denen Leute ngModules und andere Projekte verwenden Wo keine sind, führt das zu mehr Wartungs-, Schulungs- und Kompatibilitätsproblemen.

Man weiß nie, in welche Richtung dieses Projekt gehen wird, bis es fertig ist, also werden wir sehen, ob sie berücksichtigen, was du sagst.

Sogar ich arbeite derzeit daran, die Architektur für eine riesige Unternehmens-App zu entwerfen.
Im Gegensatz zu Ihrer Situation @jpsfs bin ich von NgModules begeistert und habe meine App-Architektur ziemlich auf NgModule aufgebaut.

Jedes Modul hat seinen eigenen Satz von Routen und Komponentenabhängigkeiten. Wir können niemals eine Funktionalität mit nur einer Komponente erstellen, es braucht Routen, mindestens eine intelligente Komponente und ein paar dumme Komponenten und Dienste, die dazu gehören. Stecken Sie das alles in ein Modul und Sie können loslegen.

Was Lazy Loading angeht: Anstatt Code für jede Komponente zu laden, sieht es gut aus, dass jeder NgModule-Code auf einmal geladen wird, sodass Ihre Funktionalität nach dem Herunterladen vollständig nutzbar ist.

Das Erstellen einer Hierarchie von Modulen ist ebenfalls viel einfacher und bietet eine großartige kostenlose Plug-and-Play-Funktion.

Wir arbeiten derzeit auch an einer Anwendung mit ziemlich vielen Komponenten (nicht Hunderte, sondern Dutzende). Es besteht keine architektonische Notwendigkeit für uns, diese Anwendung in mehrere (faul geladene) Module aufzuteilen, aber jetzt alle diese Komponenten in die Bootstrap-Datei zu importieren und sie an declarations zu übergeben, fühlt sich irgendwie falsch an und unterbricht die Kapselung der Komponente . Wie @jpsfs sagte, war vorher sehr klar, welche Komponenten und Anweisungen von einer anderen Komponente verwendet wurden. Daher hätte ich auch gerne die Wahl:

  • Wenn es sich um eine ziemlich häufig verwendete Direktive handelt, deklarieren Sie sie im Modul
  • Wenn es etwas wie TaskListItem ist, importieren Sie es einfach in TaskList .

Vielleicht kann ein Kernmitglied mehr über die Entscheidung sagen, den zweiten Ansatz abzulehnen. Nachdem ich jetzt mehrere Monate damit gearbeitet habe, fühlt es sich ziemlich gut an ;)

Um den Standpunkt von @choeller zu wiederholen, fühlt es sich seltsam an, sich von der Fähigkeit zu entfernen, Komponentenkapselung bereitzustellen.

Meine besondere Sorge ist, dass jetzt die Komponentennamen/Selektoren in der gesamten App durchsickern, während Sie zuvor Selektoren für verschiedene Komponenten wiederverwenden konnten, indem Sie gegebenenfalls spezifische Anweisungen einfügen.

Jetzt müssten alle Selektoren pro Komponente eindeutig sein, richtig? Oder verstehe ich die Funktionsweise falsch?

Ich hatte das Gefühl, dass die ursprüngliche Funktionalität den ähnlichen Vorteilen der CSS-Schatten-DOM-Emulation entsprach, da wir uns weniger Gedanken über Selektorkollisionen usw. in großen Apps machen mussten. Das war meiner Meinung nach ein großer Vorteil.

Mein erster Gedanke zu ngModule war „Oh, das ist wie in Winkel 1“. So toll Winkel 1 schon war, Winkel 2 ist in so vielen Punkten so viel besser. Der beste Punkt für mich war, dass Komponenten eine Art Abhängigkeitsbaum erstellen. Ich habe eine Hauptkomponente mit einem Router, der mehrere Einstiegspunkte mit einer eigenen Komponente definiert. Und jede Komponente weiß, was sie braucht, kein Grund für die Hauptkomponente, zu wissen, was eine der Komponenten am Ende des Baums braucht.
Jetzt sind wir wieder in den guten alten Zeiten von Winkel 1, wo wir eine riesige Moduldefinition haben.
Erinnerst du dich an die Zeiten, in denen dein App-Einstiegspunkt so aussah?

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("…")

Ich dachte, das gehört der Vergangenheit an. Ich habe angefangen, mit ng-metadata zu arbeiten, um alte Angular-1-Projekte zu verbessern und mich auf die Migration vorzubereiten. Ich liebe die Tatsache, dass es einen Abhängigkeitsbaum hat und keine globale Liste "was in dieser App erscheinen könnte".

Dies erschwert wiederverwendbare Komponenten. Ich verstehe nicht, wie dies die Dinge besser macht, wenn alles in einem globalen/modularen Bereich ist. Ich denke, das ng2-Team hat ng1-Benutzern nachgegeben, die keine Änderung wollen.

@DaSchTour @damiandennis Ich verstehe die Kritik an dieser Architektur, aber wenn ich mich darauf beziehe, dass eine Art globaler Geltungsbereich ungenau ist, schlagen sie vor, dass Sie Feature-Module verwenden: https://angular.io/docs/ts /neueste/guide/ngmodule.html#! #Feature-Module

@qdouble Nun, am Ende werden nur alle Komponenten in Module geändert. Obwohl dies als Änderung angekündigt wird, um Boilerplate-Code zu reduzieren, führt es eine Menge Bedarfs-Boilerplating ein.

Während bis RC4 eine Komponente für jede "Seite"/Ansicht der Anwendung ausreichte, weiß ich, dass ich für jede Ansicht ein Modul, eine Komponente und ein Routing erstellen muss. Ich verstehe die Absicht. Aber irgendwie habe ich den Eindruck, dass es darauf ausgelegt ist, einige Dinge zu erleichtern, während es viele andere Punkte nicht betrifft. Und selbst mit dem Feature-Modul-Muster muss ich sie sehr klein schneiden, um Abhängigkeitshöllen zu vermeiden, indem ich alles hinzufüge, was möglicherweise benötigt wird, weil ich nicht sehen kann, welcher Teil meiner Anwendung welche Komponenten benötigt.

Am Ende sind die Module so klein, dass sie ähnliche sich wiederholende Abhängigkeitslisten haben wie aktuelle Komponenten.

Am Ende löst es nicht das, wofür es entworfen wurde, und fügt nur eine Menge Arbeit hinzu. Ich habe das Gefühl, dass hier Design und Realität nicht zusammenpassen.

Entwickler sind faul/kurz und nehmen Abkürzungen. Dies ermutigt Entwickler, den schnellen Weg zu gehen, einfach alles in Bootstrap aufzunehmen. Zumindest bei Komponenten besteht die Anforderung, Ihre Abhängigkeiten einzubeziehen. Ja, sie können auch faul sein und eine einzelne Komponente für die gesamte Anwendung erstellen, aber das wäre einfacher zu beheben, da die Abhängigkeiten alle in dieser Komponente liegen und nicht zwischen der Bootstrap-Datei und jeder Komponentendatei innerhalb der Anwendung vermischt werden.

@DaSchTour , wenn jede einzelne Komponente ihren eigenen Bereich benötigt, dann wird es ja mehr Boilerplate erstellen ... aber ich nehme an, dass das ng-Team der Meinung ist, dass es für die meisten Leute ein neues Modul für jeden Funktionsabschnitt erstellt reicht aus und ein paar Komponenten könnten in jedem Funktionsraum leben.

Offensichtlich gibt es keine Lösung, die für alle geeignet ist, und Anweisungen auf Komponentenebene zu haben, kann für manche Leute einfacher sein. Es scheint jedoch, dass viele der Kommentare hier implizieren, dass sie möchten, dass Sie nur eine Anwendung mit einem riesigen ngModule-Baum erstellen ...

Ich denke, es ist produktiver, wenn die Kritik auf ihren tatsächlichen Designvorschlägen basiert und nicht auf einem Strohmann-Designmuster, das sie nicht vorschlagen (dh das Erstellen einer Unternehmens-App, die nur ein riesiges ngModule ist).

@qdouble das Designmuster ist einfach. Es verwendet einen Abhängigkeitsbaum, anstatt Abhängigkeiten in einen globalen Modulbereich zu verschieben. Ich denke, der Hauptpunkt ist, dass wiederverwendbare Komponenten jetzt Module sein müssen, auch wenn sie sehr klein sind und nur sehr wenig Funktionalität haben. Kantiges Material2 ist ein sehr gutes Beispiel. Ein Button ist ein Modul, das eine Komponente enthält. Vielleicht ist es ein allgemeines Missverständnis vieler Entwickler, dass ein Modul etwas ist, das mehr als nur eine Schaltfläche enthält. Und jetzt denken wir einen Schritt weiter. Ich folge nur den Ideen aus diesem Artikel https://angularjs.blogspot.com/2016/08/angular-2-rc5-ngmodules-lazy-loading.html Ich finde mich an dem Punkt wieder, dass ich viele Module habe, die Importieren Sie eine Liste von Winkelmaterial2-Modulen und jedes dieser Module besteht aus einer einzelnen Komponente.
Genau das macht Angular Material2.

Niemand versteht wirklich, warum wir jetzt "alle" unsere Komponenten in Module packen müssen. Oder vielleicht müssen wir dies als eine Aufspaltung der Erklärung sehen. Komponentenabhängigkeiten sind jetzt ein Modul und Komponentendefinitionen sind so wie sie waren.

Ich denke, der Punkt ist, dass ngModule nicht nur eine nette Ergänzung sind, um die Dinge einfacher zu machen, sondern dass wir gezwungen sind, alles zu ändern. Vielleicht sollte jemand eine klare Erklärung geben, warum nicht beide koexistieren können.

@DaSchTour Nun ja, ich stimme zu, dass, wenn jede einzelne Komponente, die Sie erstellen, ein eigenes Modul benötigt, die Verwendung von ngModules mehr Boilerplates erstellt ... Ich nehme einfach an, dass das Team nicht glaubt, dass die meisten Leute dieses Maß an Trennung für jede benötigen Komponente.

Ich befinde mich an dem Punkt, dass ich viele Module habe, die eine Liste von Winkelmaterial2-Modulen importieren und jedes dieser Module aus einer einzelnen Komponente besteht.

Sie würden dafür gemeinsam genutzte Module verwenden: https://angular.io/docs/ts/latest/guide/ngmodule.html#! #shared-modul

Nun, ich bin mir auch nicht wirklich sicher, warum sie denken, dass es notwendig ist, die Möglichkeit, einen Komponentenbereich zu haben, vollständig zu entfernen, aber für mich macht ein Teil der Kritik die Verwendung von ngModules schwieriger, als es tatsächlich ist, oder lässt das Design mehr erscheinen schlampig als es eigentlich ist.

Ich denke, die Kritik am Entfernen von komponentenbezogenen Direktiven/Pipes ist vollkommen berechtigt. Ich denke jedoch nicht, dass es notwendig ist, den Anschein zu erwecken, dass es keine guten Designmuster für ngModules gibt.

@qdouble Ich denke, niemand zweifelt daran, dass es gute Entwurfsmuster für ngModule gibt. Aber soweit ich weiß, sind Module nur ein Wrapper um eine Reihe von Komponenten, Anweisungen und Dienste, um sie bereitzustellen, sind eine Einheit für die Anwendung. Das ist gültig und eine großartige Idee. Aber warum muss ich die Abhängigkeiten (die möglicherweise nur innerhalb des Moduls existieren) für das Modul und nicht für die Komponente definieren?

Am Beispiel von @choeller
Das Modul TaskDashboard hat die folgenden Dinge

  1. Joblisten-Komponente
  2. Taskitem-Komponente
  3. Taskfilter-Komponente
  4. Aufgabendienst

Die Taskitem-Komponente wird nur innerhalb der Tasklist benötigt und die Tasklist hängt von der Taskitem-Komponente ab. Der Taskfilter benötigt die Taskitem-Komponente nicht. Jetzt habe ich das Aufgabenelement nicht als Abhängigkeit in der Aufgabenliste. Der nächste Schritt ist, dass ich ein TaskSearch-Modul erstelle. Ich füge die folgenden Dinge hinzu.

  1. Joblisten-Komponente
  2. Tasksearch-Komponente
  3. Aufgabendienst

Nun, ich habe die Taskitem-Komponente verpasst und sie ist kaputt. Tasklist hängt immer von Taskitem ab, aber diese Abhängigkeit ist im Modul ausgeblendet. Die Wiederverwendung von Komponenten wird erschwert und schafft eine zusätzliche Fehlerquelle.

Okay, beim weiteren Lesen des Modulhandbuchs habe ich diese Zeile gefunden

Komponenten, Direktiven und Pipes müssen zu genau einem Modul gehören.

Das Beispiel zeigt also genau die Bedenken, die hier geäußert werden. Es darf keine gemeinsam genutzte Komponente geben. Aus meinem Beispiel müsste ich also alles in Module aufteilen.

Während ich an den seltsamen und nicht schwer fassbaren Fehlern arbeitete, die bei der Verwendung von ngModule auftauchten, stellte ich auch fest, dass das Erweitern von Komponenten jetzt nicht mehr so ​​gut funktioniert wie zuvor. Ich hatte eine Reihe von Komponenten mit den erforderlichen Abhängigkeiten, die ich einfach erweitern konnte. Jetzt muss ich mich um den Import der Abhängigkeiten in das Modul kümmern, in das ich meine erweiterte Komponente einbinde.

@DaSchTour In Ihrem Beispiel sollte Taskitem Teil des Tasklist-Moduls sein ... das wären also logischerweise zwei Komponenten in einem Modul, nicht eine für jede.

Wie @sirajc betonte, wäre ein typisches Designmuster, eine Top-Smart-Komponente zu haben, gefolgt von zusätzlichen dummen Komponenten ... also würden in einer typischen realen App die meisten Module aus ein paar Komponenten bestehen (ob durch die Smart/Dumb Komponentenmuster oder nach verwandten Funktionsmustern), nicht nur eine Komponente pro Modul, es sei denn, Sie bauen nur Komponenten von Drittanbietern oder so etwas.

@qdouble @DaSchTour Es stimmt, dass die neue Architektur nicht unbedingt bedeutet, dass Sie alle Ihre Komponenten in einer Datei auflisten, aber wenn ich mir die App ansehe, die wir bauen, würde ich derzeit ziemlich mit dieser Aussage von @DaSchTour übereinstimmen

Ich habe das Gefühl, dass hier Design und Realität nicht zusammenpassen.

Wir haben also eine ganze Reihe von Komponenten, die kleine Einheiten auf der Seite darstellen, z. B. TaskListItem , die zu 100 % an eine spezielle Ansicht gebunden sind. Das Erstellen von Modulen für jede dieser Seiten wäre ein totaler Overkill. In unserem Fall gibt es nur sehr wenige Gründe für die Aufteilung in mehrere Module, aber viel mehr Gründe für die Kapselung von Komponenten.

tl;dr
Es ist cool, einige Abhängigkeiten auf Modulebene definieren zu können, aber es ist wirklich traurig, dass wir Abhängigkeiten nicht mehr auf Komponentenebene definieren können

@DaSchTour , In material2 ist die Schaltflächenkomponente an das Modul gebunden, um sie eigenständig zu machen. Diejenigen, die die Schaltfläche verwenden müssen, können ButtonsModule importieren. Auch wenn Sie den Modulcode sehen, enthält er zwei Komponenten MdButton und MdAnchor , das Einschließen in ButtonsModule erleichtert die Verwendung

Ich frage mich, ob es möglich ist, ein hybrides Komponenten-/Modulobjekt zu erstellen, das die beiden Konzepte zu einem zusammenführt, um die Duplizierung von Dateien zu verhindern. Im Wesentlichen ist es möglich, eine Komponente einmal als Modul zu deklarieren und sie dann bei Bedarf als Modul zu importieren. Es würde den aktuellen Ansatz respektieren, aber die Boilerplate minimieren.

@choeller Ich stimme zu, dass Module eine gute Ergänzung sind, das Entfernen von Abhängigkeiten auf Komponentenebene jedoch einfach falsch erscheint.

Anknüpfend an das, was andere oben geschrieben haben, denke ich, dass die Kernidee hier darin besteht, nicht das Elend eines riesigen Projekts mit einem riesigen Modul mit Hunderten von Komponenten darin zu erleben. Vielmehr soll eine Anwendung aus einer angemessenen Anzahl mittelgroßer NgModule aufgebaut werden. Groß genug, dass sie nicht trivial sind, klein genug, dass Sie nicht viele davon haben; entlang von Bruchlinien aufgeteilt, die die Wiederverwendung und Modularität im altmodischen Informatikverständnis von hoher Kohäsion und geringer Kopplung erleichtern würden.

Auf diese Weise sollten sich Module als recht nützliches Konzept erweisen, um sie in großen Projekten spielen zu lassen.

Das ist sehr gut zusammengefasst @kylecordes. NgModules hilft bei der netten Zusammensetzung der Anwendung. Kleine wiederverwendbare Module bilden die gesamte Anwendung.
Ein weiterer Vorteil ist die Umgebungsverfügbarkeit von Anweisungen. Früher haben wir ROUTER_DIRECTIVES in der gesamten Anwendung hinzugefügt. Jetzt erledigt RouterModule.forRoot() das für uns.
BrowserModule, CommonModule, FormsModule ist sinnvoller, als Direktiven durch jede Komponente einzufügen.

MaterialModule auf der anderen Seite bietet alles und wenn Sie eine feinere Steuerung benötigen, dann hilft uns ButtonsModule usw.
Das ist die Schönheit der Komposition. Umfassen Sie es und erstellen Sie Ihre Symphonie

Hinzu kommt LazyLoading. Wenn nicht für NgModule, wie kann man die Anzahl der Komponenten und Dienste definieren, die zusammenpassen müssen, um eine routingfähige Einheit zu erstellen? Sie können keine losen Dateien herunterladen, da dies zu einer großen Anzahl von Netzwerkanfragen führt. Andernfalls müssen Sie einen Bundler erstellen, in dem Sie alle abhängigen Dateien auflisten, um ein Bundle zu erstellen. NgModule tut dies mit intuitiver Syntax.

@kylecordes

Anknüpfend an das, was andere oben geschrieben haben, denke ich, dass die Kernidee hier darin besteht, nicht das Elend eines riesigen Projekts mit einem riesigen Modul mit Hunderten von Komponenten darin zu erleben. Vielmehr soll eine Anwendung aus einer angemessenen Anzahl mittelgroßer NgModule aufgebaut werden. Groß genug, dass sie nicht trivial sind, klein genug, dass Sie nicht viele davon haben; entlang von Bruchlinien aufgeteilt, die die Wiederverwendung und Modularität im altmodischen Informatikverständnis von hoher Kohäsion und geringer Kopplung erleichtern würden.

Wären diese Bruchlinien nicht sehr unterschiedlich für Anwendungsentwickler und Bibliotheksentwickler? Entwickler von Bibliotheken sollten in der Minderheit sein, aber das scheint die Hauptbeschwerde zu sein. Beim Aufbau eines wiederverwendbaren Frameworks führt das Ziel, die Modulgröße minimieren zu wollen, zu viel zusätzlichem Rauschen.

@sirajc

Hinzu kommt LazyLoading. Wenn nicht für NgModule, wie kann man die Anzahl der Komponenten und Dienste definieren, die zusammenpassen müssen, um eine routingfähige Einheit zu erstellen? Sie können keine losen Dateien herunterladen, da dies zu einer großen Anzahl von Netzwerkanfragen führt. Andernfalls müssen Sie einen Bundler erstellen, in dem Sie alle abhängigen Dateien auflisten, um ein Bundle zu erstellen. NgModule tut dies mit intuitiver Syntax.

Ich konnte dies mit dem alten Router problemlos tun, indem ich einfach eine Komponente verwendete, die als Container für einen Abschnitt meiner Anwendung fungierte. Dieses Modul brachte nur die direkten Komponenten ein, die es benötigte, die ihre eigenen Abhängigkeiten einbringen würden. Jeder anständige Modullader wäre in der Lage, die Abhängigkeitskette (über Importe) dieser Komponente zu laden, ohne jede Unterabhängigkeit in die Komponente der obersten Ebene aufzunehmen. Dasselbe gilt für Bundler, die eine Art Modulauflösungslogik verwenden sollten. Kurz gesagt: Aus Lazy-Loading-Perspektive gibt es keinen Grund, warum ein Entwickler alle enthaltenen Abhängigkeiten in der Komponente der obersten Ebene deklarieren muss.

Es fühlt sich wirklich so an, als wäre ngModule eine Lösung auf der Suche nach einem Problem ...

Es spricht einiges dafür, eine bestimmte Komponente öffnen zu können, einen Blick auf ihr Array mit Anweisungen zu werfen und genau zu wissen, von welchen Komponenten/Anweisungen sie abhängt. Ist es ausführlicher, eine Schaltflächenkomponente in die zahlreichen Komponenten zu importieren, die sie verwenden? Ja, aber ich hätte lieber ein paar zusätzliche Boilerplates und Dinge, die explizit und sofort durchsuchbar sind, als den Komponenten- / Modulbaum zu durchsuchen, um zu sehen, wie zum Teufel die Komponente Y die Komponente X in ihrer Vorlage verwendet, ohne sie jemals zu importieren.

Das oben angeführte Argument ist, dass jemand, der Komponenten voneinander isoliert halten möchte, wohl ein Modul für jede Komponente erstellen könnte - aber dann schreiben Sie an diesem Punkt sogar noch mehr Boilerplate, als die ursprüngliche Komponente jemals hatte.

Es gibt offensichtlich andere Vorteile von ngModule, die ich nicht behandelt habe, und obwohl es Vorteile hat, Abschnitte einer Anwendung in Funktionsmodulen bündeln zu können, fühlt es sich wirklich wie ein Rückschritt an, wenn es um Klarheit geht und wenn Komponenten gekapselt sind Code, der nicht überall Scoping durchsickern lässt.

Ein Teil des „harten Verkaufs“, den das ng2-Team gegenüber der Community von ng1 machen musste, war „Ja, Sie müssen Ihre Anweisungen für jede Komponente importieren und deklarieren, aber vertrauen Sie uns, Sie werden es zu schätzen wissen, wenn Sie expliziter sind wenn Ihre Anwendung wächst". Ich glaube fest daran, in einer großen Teamumgebung, in der ein Teammitglied möglicherweise nur an einer sehr kleinen Teilmenge von Komponenten zu einem bestimmten Zeitpunkt arbeitet, ein wenig Wiederholung aus Gründen der Lesbarkeit und Durchsuchbarkeit zu ertragen.

Zumindest sehe ich keinen Grund, warum ngModule und die Eigenschaft policies/pipes nicht koexistieren können. Die Alternative ist, dass jede einzelne Komponente in jeder einzelnen Anwendung, die für ng2 geschrieben wurde, bis zu RC5, jetzt veralteten Code verwendet, der nicht trivial umgestaltet werden muss. Das sind wirklich nicht die Art von Änderungen, die ich so spät in der Entwicklung erwarten würde ... es ist ehrlich gesagt ziemlich beunruhigend.

ngModules erfordert im Wesentlichen ein Umschreiben der meisten Anwendungen, wenn sie richtig strukturiert werden sollen ... aber das größte Missverständnis ist, dass sie eine bestimmte Umfangsebene erzwingen, wenn die Realität ist, dass Ihre Module so groß oder so klein sein können, wie Sie es möchten Sein.

Wenn Sie unbedingt für jede einzelne Komponente ein neues Modul erstellen müssen, führt dies zu mehr Boilerplate = gültig.

Die meisten Anwendungen sollten erfordern, dass Sie ein Modul für jede einzelne Komponente erstellen = ungültig (insbesondere wenn Sie intelligente/dumme Komponentenmuster und Funktionsmuster verwenden).

Heute habe ich zum ersten Mal die Client-Side-/JavaScript-Müdigkeit gespürt, die mir einige Kollegen vermittelt haben. Ich habe in den letzten Tagen unzählige Stunden damit verbracht, unsere RC4-Anwendung so umzugestalten, dass sie die neuen RC5-Module verwendet.

Ich stimme definitiv einer Reihe von Meinungen in diesem Thread zu, insbesondere darüber, Entwicklern die Wahl zu lassen, wie sie ihre Komponentenabhängigkeiten strukturieren möchten. Ich mag es nicht, dass ein größeres ngModule das klare Abhängigkeitsdiagramm zwischen Komponenten verwässert und dass kleinere ngModule jeder Komponente zusätzlichen Boilerplate-Code hinzufügen. Bei der Analyse eines Moduls weiß ich nur, dass mindestens eine der referenzierten Komponenten Daten aus den Importen oder Geschwisterdeklarationen des Moduls benötigt. Wenn ich ein Modul in mehrere andere Module zerlege, muss ich im Grunde nur durch Versuch und Irrtum feststellen, welche Abhängigkeiten die neuen Module benötigen (eine sorgfältige Prüfung der Komponentenvorlage hilft etwas).

Schließlich, wenn ich "vergesse", Komponenten zu exportieren, wird meine Komponente einfach nicht gerendert, es werden keine Fehler ausgegeben. Es ist leicht zu finden, wenn Sie ein sehr flaches Moduldiagramm haben, fast unmöglich, wenn Sie eine Reihe von Ebenen haben!

In diesem Stadium bin ich niedergeschlagen, enttäuscht und entmutigt. Ich habe ein Team von Entwicklern und Geschäftsinteressenten mit einer Technologie an Bord geholt, von der ich jetzt nicht weiß, ob ich sie voranbringen kann. Ich hoffe wirklich, dass eine bessere Balance gefunden werden kann.

In diesem Stadium bin ich niedergeschlagen, enttäuscht und entmutigt. Ich habe ein Team von Entwicklern und Geschäftsinteressenten mit einer Technologie an Bord geholt, von der ich jetzt nicht weiß, ob ich sie voranbringen kann. Ich hoffe wirklich, dass eine bessere Balance gefunden werden kann.

Ich denke, der Punkt hier ist, dass es eine riesige Anzahl von Entwicklern gibt, die darauf warten, dass diese Technologie für die Produktion bereit ist, und obwohl sie Release Candidate heißt, bringt jeder neue Kandidat Breaking Changes mit sich und es fühlt sich eher wie ein Alpha an.

Ich bin sicher, dass viele Teams Stunden mit der Architektur ihrer neuen Apps verbracht haben, und jetzt ist alles verrückt.

Was wird die nächste bahnbrechende Änderung sein? Ich kann es mir nicht einmal vorstellen, aber ich befürchte, dass jemand einen Weg finden wird, die nächste bahnbrechende Änderung einzuführen.

Aus dem RC5-Blogbeitrag:

Wenn Sie jedoch überhaupt Angular 2-Code geschrieben haben, haben Sie sich wahrscheinlich gefragt: "Aber WARUM muss ich all diese Dinge auflisten!?" - insbesondere wenn Sie bemerkt haben, dass bestimmte Direktiven und Pipes in Angular 2 "besonders" sind - sie stehen Ihrer gesamten Anwendung zur Verfügung, ohne dass Sie etwas tun müssen (z. B. *ngFor / *ngIf / *ngSwitch).

Ich persönlich habe diese Frage seit geraumer Zeit nicht mehr von jemandem gestellt gesehen. Bis zum RC5 haben das Angular-Team, Online-Lernressourcen, Bücher usw. alle ziemlich klar gemacht, warum diese Erklärungen benötigt werden – und es scheint, als ob jeder diese Tatsache vor langer Zeit akzeptiert (und einige angenommen) hat.

Was die Fragen anbelangt, warum einige „besonders“ sind und nicht deklariert werden müssen, glaube ich nicht, dass irgendjemand dagegen argumentieren würde, dass es eine Liste kritischer „niedriger“ Richtlinien gibt, die so allgegenwärtig sind, dass sie es rechtfertigen, „gesegnet“ zu werden. wie vom Plattforminhaber (Angular-Team) global verfügbar.

Wenn der Code bereits vorhanden ist, um das Hochziehen der Anweisungen in ein einzelnes ngModule zu handhaben, und dieser Code für den Endbenutzer unsichtbar funktioniert, was schadet es dann, beide Ansätze zuzulassen? Das ist eine echte Frage, da ich mir möglicherweise einiger der Feinheiten nicht bewusst bin, was passieren könnte, wenn ein Entwickler den Ansatz mischt und anpasst. Es gibt in Angular 2 viele andere „Split-Choices“ – modellgesteuerte vs.

Ich könnte weitermachen, aber ich versuche hervorzuheben, dass das Angular-Team und die Community ziemlich viel Zeit investiert haben, um die Botschaft einzuhämmern, dass es eine _gute_ Sache ist, expliziter zu sein, nur um dann bei _Release einzuspringen ausgerechnet Kandidat 5_ -- um uns eine Lösung zu präsentieren, die seit geraumer Zeit kein Problem mehr ist.

Hat jemand aus dem Team Lust, sich einzumischen? Ich möchte nicht, dass dies zu einer Echokammer wird – ich würde gerne die andere Seite des Arguments hören. Es scheint einfach so, als ob etwas so Großes aus heiterem Himmel kam, ohne Rücksicht auf Dinge wie Werkzeuge, Schulungen oder wie nahe wir der endgültigen Veröffentlichung zu sein scheinen.

Diese Diskussion warf ein sehr großes Problem für viele Entwickler auf, die früh mit der Entwicklung der mit Spannung erwarteten 2 : Breaking Changes beginnen wollten. Ich habe seit Beta 17 eine Reihe von Proof-of-Concepts basierend auf Angle 2 durchgeführt und wichtige Unternehmen und Organisationen dazu gebracht, es zu übernehmen. Ich bereue es nicht, aber ich bin mir auch nicht sicher, ob ich es gut gemacht habe. Einige der neuesten Projekte waren ein POC und der Kampf war gegen Vue.js. Angular 2 hat diesen Kampf eindeutig gewonnen. Aber heute, mit all dem Umschreiben des Codes, Breaking Changes, nicht wirklich RC-Veröffentlichungen, fangen die Leute an, mich zu jagen, und es wird ziemlich ernst. Es wäre nicht der Fall gewesen, wenn ich eine Vue- oder React-Entwicklung angeboten hätte, und das ist sehr frustrierend, weil Angular 2 Menschen in Misskredit bringen kann.

Es scheint mir sehr, dass ich nicht dieselbe Definition von Release Candidate teile wie das Angular-Team.

Was das Thema NgModule betrifft, unterschreibe ich @jpsfs vollständig mit. Wenn Sie alle Ihre Komponenten und Mikrokomponenten in Ihrer Moduldeklaration auflisten müssen, sollten Sie besser irgendwo eine prune -Funktion haben oder die sein König der Modellierung, denn so mächtig es auch sein mag, es ist zu empfindlich für große Projekte ...

Ich denke, dass dieses zusätzliche höhere Maß an Modularität fast unvermeidlich war; und dass verschiedene konkurrierende Frameworks schließlich zu etwas Analogem führen werden.

Ich frage mich jedoch, ob es wirklich notwendig war, dieses neue grobkörnige Modulsystem vollständig orthogonal zum zugrunde liegenden Modulsystem zu machen, oder ob es möglich gewesen wäre, jedes Top-Level-Verzeichnis und alle darin enthaltenen Es6-Module implizit zu erstellen umfassen ein grobkörniges NgModul. Vielleicht könnte ein solcher konventionsgesteuerter Mechanismus zusätzlich zum aktuellen Mechanismus hinzugefügt werden und daher die NgModule-Boilerplate für Projekte entfernen, die bereit sind, einer solchen Konvention zu folgen.

(Natürlich teile ich hier auch mit anderen die Frustration über solch signifikante Veränderungen in der "RC"-Phase ... Ich bin mir jedoch sicher, dass auch das Kernteam, wenn sie alles noch einmal machen müssten, auf hohem Niveau angegriffen hätte Modularität und die Kräfte, die sie vorantreiben (faules Laden, Vorkompilierung), viel näher an den Beginn des Projekts als in die Phase der Veröffentlichungskandidaten. So ist das Leben jedoch, es ist immer leicht, zurückzublicken und zu denken: "Gut, wenn wir damals gewusst, was wir heute wissen...")

Wenn die Kompilierungsunterstützung der Hauptgrund für das Erscheinen des ngModuls ist, sollte es definitiv nicht den bestehenden komponentenbasierten Bereich für Direktiven und Pipes ersetzen.
Andererseits könnte der Angular-Compiler basierend auf Routenkonfiguration und Abhängigkeiten den Anwendungscode theoretisch selbst in die entsprechenden Kompilierungseinheiten (Module) aufteilen.

Ich persönlich habe das Gefühl, dass diese Änderung einen Tiefpunkt ohne großen Vorteil bringt.

Ich könnte argumentieren, dass wir anstelle von Modulen auch Komponenten als Einheiten der Anwendung hätten verwenden können. Das haben die Leute wahrscheinlich sowieso vor RC-5 gemacht.

Wenn die Module für interne Zwecke dieses Frameworks benötigt werden (wie Lazy Loading und verwandte Dinge), sollten sie irgendwie vor dem Entwickler verborgen werden, damit sie den Code nicht verschmutzen und zu einer schlechteren Codierungserfahrung führen. Und ich spreche noch nicht einmal von Wartbarkeit ...

Als ich Angular2 zum ersten Mal sah, dachte ich: 'Hey, sie gehen damit in die richtige Richtung, es scheint, als hätten sie etwas von Angular 1 gelernt'. Sie haben die internen Module von Angular 1 fallen gelassen und stattdessen ES-Module verwendet, andere Änderungen wurden ebenfalls begrüßt (Komponenten, Typoskript usw.)

Aber je länger ich darauf warte, dass es stabil wird, desto mehr schaudert es mich wegen Breaking Changes, fehlender Dokumentation und schlechten Fehlermeldungen. Jetzt kommen Sie mit diesen NgModulen und machen im Grunde mindestens eine großartige Sache rückgängig, die Sie seit Winkel 1 geändert haben.

Schlimmer noch, wenn ich eine App habe, die mit rc-2 oder 3 gestartet ist (die theoretisch fast stabil waren), muss ich jetzt viel Arbeit leisten, um eine gute angle2 rc-5-App zu erstellen, und muss dem Kunden und anderen irgendwie erklären Entwickler dies. Und selbst wenn ich das tue, weiß Gott, was Sie als nächstes ändern werden, und meine Arbeit könnte im Sande verlaufen sein.

Ich weiß, dass Angular 2 schon seit einiger Zeit im Frühstadium ist, aber wir sind RC-5, die Leute haben inzwischen ziemlich solide Projekte, die Angular 2 verwenden, und Sie nehmen immer noch Änderungen vor, die nicht nur aus Sicht der API brechen, sondern auch als Weg in Angular zu denken.

Es ist nicht gut, dass ngFor und einige Importe sich ändern oder dass sich das Einfügen von Komponenten in 5 Versionen dreimal dynamisch ändert, aber das kann ich akzeptieren und verstehen. Änderungen zu bringen, die nicht nur Apps kaputt machen, sondern auch die Art und Weise, wie Entwickler in diesem Rahmen so spät im Entwicklungszyklus denken, kann ich leider nicht akzeptieren.

Jedenfalls stimmen, wie Sie sehen können, viele Leute mit dem überein, was ich zu sagen habe, und einige sind sogar noch wütender. Sie haben ein riesiges Framework, dem die Leute vertrauen (weil Google meistens), aber Sie können nicht alles darauf setzen, oder Sie könnten eine Überraschung erleben, da jeder die Wahl hat (und wenn es um JS geht, gibt es VIELE).

Wenn das neue Modul eine Vorlage hätte, könnte es die Komponente sein. Denk darüber nach.

Der nächste Schritt wäre, alle Variablen und Funktionen von Components in die Module-Klasse zu verschieben. Ernsthaft. Dann hatten wir eine riesige zentrale Bibliothek mit _allen möglichen_ Aktionen in unserem glänzenden Modul. Das wäre toll! Ich weiß nicht, warum Sie bei der Zentralisierung von Deklarationen und Abhängigkeiten stehen geblieben sind. Da gibt es noch viel mehr dezentrale, strukturierte Codezeilen!

Kann irgendjemand aus dem Kernteam zu all dem etwas sagen? Aus den Notizen des letzten wöchentlichen Meetings geht hervor, dass das Team mit der Entfernung der veralteten APIs fortfährt.

@mhevery

Diese ganze Hebe-Sache hat meine Anwendung beim Upgrade heute ganz subtil kaputt gemacht.

  • Ich musste den Selektor einer Komponente von Klasse zu Element ändern, da diese Klasse in einer völlig unabhängigen Komponente für das Styling verwendet wird und plötzlich damit begann, die Komponente zu instanziieren.
  • Ich bin mir ziemlich sicher, dass nur #10850 existiert, weil ich zwei Komponenten namens SpectrumComponent hatte (eine ganze Seite, zu der ohne einen Selektor navigiert werden kann, und eine „gemeinsame“ Komponente, die in mehreren Komponenten zur Visualisierung mit einem Selektor verwendet wird). Hoisting wird dadurch wahrscheinlich verwirrt - directives: Deklarationen nicht.

Für meine SVG-Komponenten wird dies nun zu einem größeren Problem, da ich dort kein benutzerdefiniertes Element verwenden kann. Ich weiß noch nicht, wie ich diese ausrichten soll, um sicherzustellen, dass ihre Klassenselektoren nirgendwo sonst (!) in der Anwendung eine Komponenteninstanziierung auslösen.

Es scheint heutzutage en vogue zu sein, die Bedeutung von „Beta“ und „Release Candidate“ (ASP.NET Core ist ein weiteres prominentes Beispiel) in großen Projekten zu ignorieren. Es ist jedoch frustrierender, als es sein sollte, mit Breaking Changes konfrontiert zu werden, die das Potenzial haben, eine Anwendung buchstäblich überall stillschweigend zu beschädigen. Ich hoffe wirklich, dass die Versprechungen, die mit diesen Änderungen einhergehen, bald Früchte tragen.

ngModules macht Sinn. Das Entfernen der Fähigkeit zum Deklarieren/Bereitstellen auf Komponentenebene tut dies nicht.

Kleines Beispiel

Ich habe eine Anwendung, die eine Reihe verschiedener Dialoge enthält (einige einfache - nennen wir sie einfach-1 und einfach-2, und eine komplexe, die andere Komponenten enthält - nennen wir diese komplexe 3).

Im Moment habe ich eine einfache Ordnerstruktur (offensichtlich sitzt die App aus dieser heraus)

- 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

Für mich ist dies ein perfektes Feature-Set, um es in ein isoliertes Feature-Modul einzubauen. Also füge ich hinzu

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

Und ich füge Simple1Component, Simple2Component und Complex3Component als Deklarationen zu DialogsModule hinzu. Perfekt, funktioniert gut und macht absolut Sinn.

Aber...

Was ist mit all diesen internen Komponenten in Komplex-3? Ich habe jetzt zwei Möglichkeiten

  • Fügen Sie DialogsModule alle externen komplexen Komponenten und Dienste hinzu. Dies ist eine schlechte Entscheidung, da die Kapselung von Komplex-3 unterbrochen wird, da jetzt alles im Dialogmodul über seine Interna weiß (interne Komponente-1, interne Komponente-2, interner Dienst-3).
  • Machen Sie complex-3 zu einem eigenständigen Modul. Dies behebt das Scoping-Problem (und ich glaube, ich kann Module aus einem anderen Modul exportieren, sodass der Client nur das Wrapper-Modul importieren muss), aber ich habe jetzt eine Mischung aus Komponenten und Modulen für ähnliche Gruppen (Dialoge).

Keines davon macht wirklich Sinn, und wenn die Anwendung skaliert, wird der Konflikt zwischen den beiden nur noch zunehmen.

Die einzige vernünftige/offensichtliche/wartbare Lösung für mich wäre, das Modul zu verwenden, um die Komponenten der obersten Ebene (simple-1, simple-2, complex-3) zu exportieren, aber die complex-3 _component_ ihre eigenen internen Komponenten selbst definieren zu lassen.

/cc: @robwormald

Ich habe darüber nachgedacht, was @kylecordes vorhin über die Verwendung des bestehenden Typescript-Modulsystems zum Definieren von grobkörnigeren Codesammlungen gesagt hat, anstatt das neue ngModules-Ding hinzuzufügen. Ich möchte ein Beispiel zur Prüfung einreichen, das Typescript-Module verwendet, um ngModules 1-zu-1 zu definieren. Kommentare und Gedanken sind willkommen.

https://github.com/jbalbes/autoNgModule

10901

Ich habe vielleicht etwas übersehen, aber die Art und Weise, wie die Abhängigkeitsinjektion mit nicht verzögert geladenen Modulen funktioniert, könnte zu einem großen Problem für "Große Projekte" werden (meins ist es nicht und es leidet bereits).

das ist interessant. Wir haben bereits eine Unternehmensanwendung auf Angular1. und wir verwenden requirejs, um Pakete für verschiedene Module zu definieren (jedes Modul enthält 10-20 Anweisungen/Dienste/Filter). Wir bündeln diese Pakete in einer einzigen Datei für die Produktion (außer Hauptdirektiven). Direktiven werden träge in die Anwendung geladen, wenn sie verwendet werden (wir haben eine Kerndirektive, die die erforderlichen Direktiven träge lädt).

Unsere Seitenvorlagen für das Anwendungs-Routing sind in der CMS-Anwendung untergebracht, und CMS-Benutzer können auf Hauptanweisungen basierende UI-Widgets zwischen verschiedenen Seitenvorlagen ziehen und ablegen (aus diesem Grund benötigten wir eine Lazy-Load-Unterstützung für Anweisungen, um die Größe der Hauptskriptdatei beim Laden des Browsers zu reduzieren als die meisten unserer Anwendungen basieren auf richtlinienbasierten Widgets)

Angular1 ermöglicht das verzögerte Laden von Anweisungen in ein Modul, indem es einen Verweis auf Registrierungsanbieter erhält.
Ist diese Art von verzögertem Laden von Komponenten in ein Modul und Kompilieren in Dom möglich in Angular2?

Ich stimme dem zu, was andere vorgeschlagen haben, dass ngModules eine Lösung ist, die nach einem Problem sucht. Der potenzielle Nutzen von LazyLoading rechtfertigt meiner Meinung nach nicht die erzwungene Ablehnung von Abhängigkeiten von Komponentendirektiven/Pipes. Vielleicht irre ich mich hier, aber ich habe das Gefühl, dass die Mehrheit der Anwendungen keinen wirklichen Nutzen aus Lazy Loading ziehen wird, was für mich der einzige wirkliche Vorteil ist, den ngModules überhaupt bietet.

Vielleicht versucht ngModules (und hey, vielleicht wird es gelingen), die Entwicklungsstruktur/-muster schöner zu machen, aber basierend auf dem Wenigen, das ich mir bisher angesehen und die API besprochen habe, bewegt es sich in eine Richtung, die einfach komplizierter ist verfolgen und pflegen.

Und brauchen wir wirklich ein weiteres Modulsystem?

Niemand kann bestreiten, dass NgModule etwas Neues hinzufügt, mit dem wir uns vorher nicht befassen mussten. Und ich schätze ebenso wie jeder andere die Einfachheit vor RC5, insbesondere bei sehr kleinen Programmen, die verloren gegangen ist. Ich vermisse es auch sehr, den Leuten sagen zu können, dass Angular 1 ein eigenes Modulsystem hatte, aber mit Angular 2 verwenden wir nur das Modulsystem der zugrunde liegenden Sprache. Hoppla.

Es gibt jedoch tatsächlich eine ganze Menge Leute, einschließlich vieler technischer Leiter und anderer Entscheidungsträger in großen Unternehmen, die versuchen, große Dinge zu bauen, die extrem an Lazy Loading und Template-Vorkompilierung interessiert sind ... Beides ist im Wesentlichen möglich von NgModule.

Aber noch etwas. Der Teil, den ich an den neuen Angular-Modulen am wenigsten mag, ist der Name. Das Wort Modul, es ist so überladen. Ich habe gestern hier für einige andere Entwickler darüber gesprochen, und wir mögen stattdessen das Wort "Paket", es fängt eine ähnliche Idee gut ein und es gibt nicht viele konkurrierende Dinge mit demselben Namen, zumindest nicht im JavaScript-Ökosystem.

@kylecordes Problem mit dem Namen https://github.com/angular/angular/issues/10087

Würde die dort vorgestellte Logik nicht auch die Verwendung des Wortes "Modul" disqualifizieren, da es mit ebenso vielen, wenn nicht mehr Konzepten in Konflikt gerät?

@Barryrowe hätte es selbst nicht besser sagen können - es scheint wirklich so, als würden die meisten Apps davon nicht profitieren - wird es am Ende nur zu einer zusätzlichen Komplexität? Ich hoffe nicht.

Ich frage mich jedoch, ob es wirklich notwendig war, dieses neue grobkörnige Modulsystem vollständig orthogonal zum zugrunde liegenden Modulsystem zu machen, oder ob es möglich gewesen wäre, jedes Top-Level-Verzeichnis und alle darin enthaltenen Es6-Module implizit zu erstellen umfassen ein grobkörniges NgModul. Vielleicht könnte ein solcher konventionsgesteuerter Mechanismus zusätzlich zum aktuellen Mechanismus hinzugefügt werden und daher die NgModule-Boilerplate für Projekte entfernen, die bereit sind, einer solchen Konvention zu folgen.

Dies ist ein wichtiger Punkt. ESModule eignen sich sehr gut zur Strukturierung einer Bewerbung, wenn Sie Ihre Bewerbung richtig strukturieren. Beispielsweise können Sie einen tief verschachtelten Export ganz einfach auf der obersten Ebene Ihrer API verfügbar machen, indem Sie ihn einfach auf einer höheren Ebene erneut exportieren. Ich bin auch dafür, dem Framework im Allgemeinen weitere optionale Konventionen hinzuzufügen.

Als ich Angular2 zum ersten Mal sah, dachte ich: 'Hey, sie gehen damit in die richtige Richtung, es scheint, als hätten sie etwas von Angular 1 gelernt'. Sie haben die internen Module von Angular 1 fallen gelassen und stattdessen ES-Module verwendet, andere Änderungen wurden ebenfalls begrüßt (Komponenten, Typoskript usw.)

Aber je länger ich darauf warte, dass es stabil wird, desto mehr schaudert es mich wegen Breaking Changes, fehlender Dokumentation und schlechten Fehlermeldungen. Jetzt kommen Sie mit diesen NgModulen und machen im Grunde mindestens eine großartige Sache rückgängig, die Sie seit Winkel 1 geändert haben.

Tatsächlich sollte Angular 2 den reichhaltigen, aufstrebenden Web-Technologie-Stack nutzen, der bei der Entwicklung von AngularJS nicht verfügbar war. Doch während die Rechtfertigung für so viele der für Angular 2 getroffenen Designentscheidungen „Webkomponenten müssen unterstützt werden“ lautet, weicht das Framework ironischerweise immer mehr von Standards ab. Nun gibt es gute Gründe, vom Standard abzuweichen, wenn der Standard schlecht ist.

Ich habe das Gefühl, dass das Framework seine Kernwerkzeuge nicht voll ausschöpft. Beispielsweise sind die TypeScript-Deklarationen nicht gerade idiomatisch und mit any und any[] übersät. Sie ignorieren auch leistungsstarke Sprachfunktionen, die die Benutzerfreundlichkeit und Toolability von APIs verbessern. Sie enthalten auch abscheuliche Dinge wie export declare type Type = Function .

Interessanterweise hat sich herausgestellt, dass eine ganze Reihe von Entscheidungen Dart-bezogen waren. Dart interessiert die meisten Angular-Benutzer nicht. Es hat im Vergleich zu TypeScript eine ganz andere Vorstellung davon, was Typen sind und wie sie verwendet werden. Dart <-> JavaScript Interop ist oft ein Nichtstarter.

@aluanhaddad , die Dart-Implementierung wurde kürzlich in ein separates Projekt ausgegliedert, also werden hoffentlich einige Ihrer Bedenken bald behoben.

Diese Änderung hat ein erhebliches Maß an Komplexität hinzugefügt, sowohl in Bezug auf die Gesamt-LOC als auch auf die mentale Modellierung von Komponentenabhängigkeiten. Meine Komponentendateien sind etwas sauberer, aber auf Kosten der expliziten und direkten Abhängigkeitsdefinition und kommen mit dem Hinzufügen von redundanten .module-Dateien.

Das Reduzieren von Boilerplates klingt nach einer guten Sache, aber ich würde argumentieren, dass es übertrieben werden kann. Darüber hinaus scheint es, dass diese besondere Anstrengung zur Reduzierung von Boilerplates besser als eine Bewegung von Boilerplates im Gegensatz zu einer vollständigen Reduzierung beschrieben werden kann.

Ich denke, eckig tendiert zu schwierigeren und komplexeren Schnellstarts. Es gibt bereits einiges zu tun, was die Einrichtung der Toolchain betrifft, und die Liste der Dateien und Dinge, die verstanden werden müssen (wenn man sich an Best Practices halten will), wächst sogar für die Barebone-Anwendung.

. @jbalbes danke, das freut mich zu hören.

@radusuciu Sie haben absolut Recht, dies ist keine Reduzierung der Boilerplate, sondern eine Übertragung dieser Boilerplate auf einen anderen Anwendungsbereich. Wie bereits von anderen gesagt wurde, gibt es hier keinen Konflikt zwischen dem Scoping auf Komponentenebene und dem Scoping auf NGModule-Ebene. Was wir brauchen, ist ein granulares Scoping, damit wir auswählen können, welche Komponenten, Anweisungen, Pipes und Dienste verfügbar sein sollten, um die Anwendung basierend auf ihrer anwendungsspezifischen Verwendung und Semantik zu entlasten

Es ist für mich kein Wunder, dass Module dem App-Autor noch mehr Komplexität von zweifelhaftem Wert hinzufügen. Sie waren nicht Teil des ursprünglichen Designs und scheinen eine späte Ergänzung zu sein, die nur hinzugefügt wurde, weil andere Dinge an eine Wand stießen und nicht zum Laufen gebracht werden konnten (faules Laden, Kompilieren usw.), ohne dass eine weitere größere Änderung vorgenommen wurde.

Ich glaube nicht, dass alle Auswirkungen auf die App-Entwicklung im Vergleich zu „die anderen versprochenen Funktionen zum Funktionieren bringen“ so weit oben auf der Tagesordnung standen, als sie hinzugefügt wurden, aber je mehr und größere Apps auf RC5 konvertiert werden, desto klarer werden sie.

Ich habe noch nicht einmal angefangen zu versuchen, meine App in Module umzuwandeln, sie wird wahrscheinlich auf RC4 sterben. Ich weiß, dass so viele Teile komplett überarbeitet werden müssen, und alles, was ich für all diese Bemühungen bekommen würde, wäre, mit noch größeren Laufzeitpaketen näher am nächsten Breaking Change RC zu sein, weil die Minimierung, sicherlich etwas ziemlich Grundlegendes und Grundlegendes, kaputt ist . RCs sollen stabiler werden und sich fertiger anfühlen, wenn sie Fortschritte machen, das tut es einfach nicht.

Gang, NgModule ist eine Irritation, wie viele eloquent erklärt haben. Aber praktisch ist es nicht so eine große Sache. Hier drüben (Oasis Digital / Angular Boot Camp) haben wir bereits zahlreiche kleine Dinge und ein paar nicht so kleine Dinge auf RC5 aktualisiert, und es war in kurzer Zeit erledigt (nach einer langen Zeit des Lernens und Verstehens).

Jede App wird unterschiedlich betroffen sein. Außerdem denke ich, dass Ihre Einstellung zu Abwanderung und Änderungen in Angular 2 möglicherweise anders sein wird, wenn Sie sich auf die Bereitstellung einer App konzentrieren, als wenn Sie auch Schulungen und Support für Angular 2 verkaufen. Für mich wäre die ganze Arbeit für ein Upgrade auf RC5 völlig tot und verschwendete Mühe sein - es würde tatsächlich negative Vorteile bringen (größere Bündel), also ist es schwer zu rechtfertigen.

Ich dachte nur, ich würde meine Gedanken, die aus der Kehrseite eines fünftägigen Vorstoßes auf unserer Plattform kommen, um zu RC6 * zu kommen (wir sind auf Nightlies, RC6 ist zum Zeitpunkt des Schreibens noch nicht technisch gesehen) schildern. Ich habe das Gefühl, dass, obwohl meine ursprünglichen Kommentare immer noch gültig sind, ich ein Gefühl der Erleichterung verspüre, diesen Meilenstein erreicht zu haben. Die größten Probleme bestehen weiterhin in der Verwendung der neuen Routing-Syntax - viel zu viele leere path: '' -Regeln! (Ich schweife ab) aber das ist etwas, das wir wahrscheinlich abstrahieren werden.

Für NgModule in den Nightlies muss ich sagen, dass die Fehlermeldungen besser werden, wodurch der gesamte Prozess ein wenig einfacher zu handhaben ist. Komponenten und Direktiven werden normalerweise aufgerufen, wenn sie nicht richtig konfiguriert sind und genügend Informationen enthalten, sodass Sie nicht durch einen riesigen NgModule-Abhängigkeitsbaum gehen, um das Problem zu finden. Das Hauptproblem, auf das wir jetzt stoßen, ist nur die fehlende Funktionalität auf Seiten ohne offensichtliche Fehlermeldungen. Dies liegt normalerweise daran, dass eine Komponente nicht korrekt deklariert oder importiert/exportiert wurde. Es ist ein wenig knifflig, aber mit Bildung ist es leicht genug, damit umzugehen. Das Testen ist jetzt unser nächster Schub, es ist völlig tot im Wasser. Aber wie beim Funktionsschub werden wir am Ende dorthin gelangen.

Wir haben tief durchgeatmet, ein paar Tage etwas anderes gemacht und dann geschmissen. Wir halten uns fest für die nächste Fahrt, was auch immer das ist! Viel Glück allen, die davon im Kleinen oder Großen betroffen sind. Es wäre schön gewesen, eine Art Dialog mit dem Angular-Team zu diesem Thema zu haben. Das schwierigste Problem, mit dem wir konfrontiert waren, war der Mangel an Kommunikation. Wir wissen immer noch nicht, was für NgModules auf den Karten steht. Die Sitzungsnotizen der letzten Woche boten keine Einblicke. Mal sehen, was diese Woche passiert!

@SaltyDH Ich denke, das ist wertvolles Feedback.
Ich finde die Beschwerden über die Kommunikation nicht wirklich angebracht.

Die Leute für die Implementierung erstellen die neue Version und die Leute für die Dokumentation aktualisieren die Dokumentation.
Die Dokumente sind aus offensichtlichen Gründen normalerweise etwas im Rückstand, da sie nur dokumentieren können, nachdem es bereits codiert wurde. Das Schreiben von Dokumenten ist auch eine harte und zeitaufwändige Arbeit.

Wenn Sie am Tag der Veröffentlichung auf die nächste Version wechseln oder sogar Nightlies verwenden, ist es etwas unfair, sich darüber zu beschweren, dass noch nicht alles kommuniziert wurde.
Das Angular-Team kann auch nicht im Voraus wissen, was den Benutzern in allen Fällen Schwierigkeiten bereiten könnte.

Es gibt immer Mitglieder des Angular-Teams, die Unterstützung bei Gitter und Problemen bieten.
Sie sollten sich auch bewusst sein, dass die Kommunikationslast ziemlich asymmetrisch ist, mit einigen wenigen Angular-Teammitgliedern für Tausende von Entwicklern.

Ich stimme vollkommen zu, dass dies für den Master-Build (fast RC6) einfacher ist, da die Abwertungen des letzten Jahres endlich verschwinden.

@kylecordes Inwiefern wird es einfacher, mit dem Master zu arbeiten?

Das Designdokument für NgModules (früher bekannt als AppModules, als das Designdokument geschrieben wurde) wurde vor mehr als einem Monat vor der Veröffentlichung von RC5 veröffentlicht, und ich war irgendwie darauf vorbereitet, dass es kommen würde.
Da NgModule ein neueres Konzept war, war es außerdem schwierig, es vollständig zu erfassen und Ihre mittelgroße auf große App zu migrieren.
Was ich stattdessen getan habe, ist, zuerst die Nuancen von NgModules vollständig zu verstehen und wie man in NgModules denkt , um eine Angular 2-Anwendung zu entwerfen. Dann eine selbstlernende App mit Anwendung von NgModules erstellt.
Der zweite Schritt ist - überlegen Sie, wie die aktuelle App in Module unterteilt werden kann, und migrieren Sie sie dann von oben nach unten. Erstellen eines Moduls nach dem anderen, beginnend mit AppModule. Das hat wirklich geholfen und die endgültige App sieht organisierter aus.
image

Und ja, Gitter war wirklich hilfreich bei der Bereitstellung von Hilfe zu NgModule, noch bevor RC5 veröffentlicht wurde. Nach RC5 stehen uns Dokumente und Blogs zur Verfügung, damit wir viel besser lernen können.

@zoechi Ohne diese Diskussion zu sehr zu entgleisen, muss ich meine Kommentare klarstellen. Ich habe mich überhaupt nicht auf die Dokumentation bezogen, die meisten meiner Erkenntnisse stammen aus der Überprüfung von Commits und Issues hier in GitHub, damit bin ich einverstanden. Meine Frustration kommt von einem Mangel an Vertretung hier in dieser Ausgabe, wir sind bei 61 Kommentaren und zählen. Ein einfaches: "Wir sind uns der Bedenken aller hier in dieser Ausgabe bewusst, wir glauben wirklich, dass dies der beste Ansatz für Angular 2 ist, und wir erkennen die Schwierigkeiten, die es verursachen wird, aber es ist besser für die Zukunft des Produkts." Gitter ist großartig, aber einzelne Nachrichten gehen oft in einem Meer von Menschen verloren, die versuchen, verschiedene Aspekte von Angular 2 zu verstehen. Ich habe mich über dieses Medium gemeldet, aber aufgrund von Zeitzonenunterschieden oder anderen Prioritäten konnte ich kein maßgebliches Feedback erhalten I verwenden könnte, um eine fundierte Entscheidung zu treffen. Was geholfen hat, war dieser Adventures in Angle Podcast https://devchat.tv/adv-in-angular/106-aia-angular2-rc5-and-beyond. Dies gab mir das Vertrauen, mit den NgModule-Upgrades fortzufahren.

Alles Gute.

Vielen Dank für das Feedback an alle. Entschuldigen Sie, dass es so lange gedauert hat, bis Sie eine Antwort erhalten haben. Wir waren in der letzten Woche sehr beschäftigt (Migration interner Google-Apps auf NgModules, daher spüren wir auch den Refactoring-Schmerz).

Lassen Sie mich sehen, ob ich einige der Fragen und Missverständnisse hier klären kann.

Das Erste, was man über @NgModule() (und @Component und jeden anderen Angukar-Dekorator) verstehen muss, ist, dass sie ein reines Kompilierzeitkonstrukt sind – sie existieren, damit der eckige Compiler einen Abhängigkeitsgraphen in einer Anwendung entdecken kann.

Eine (vereinfachte) Version dessen, was unsere Dekorateure tun, sieht so aus:

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

Sie ändern oder modifizieren das Verhalten der dekorierten Klasse in keiner Weise – sie hängen einfach einige Metadaten an. Angular verwendet diese Metadaten, um Ihre Anwendung zu erstellen und Vorlagen zu kompilieren.

Im JiT-Modus geschieht dies „Just in Time“ – zwischen dem Aufruf von bootstrapModule und dem Rendern der ersten Komponente ruft der Compiler von Angular die an Klassen angehängten Metadaten mithilfe der Reflect-API ab:

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

Im AoT-Modus funktioniert dies jedoch etwas anders – zur Build-Zeit extrahieren wir _statisch_ (d. h. ohne Ausführung Ihres Codes) dieselben Metadaten aus dem Quellcode, indem wir nach Decorators suchen.

Dies funktioniert gut, wenn Sie eine einzelne Komponente booten, aber wir haben viel Feedback von Entwicklern gehört, die komplexere Dinge tun – Bootstrapping mehrerer Root-Komponenten oder Bootstrapping verschiedener Komponenten basierend auf dem Authentifizierungsstatus usw.

Während @Component decorators uns also die Möglichkeit gab, eine Komponente statisch zu analysieren, hatten wir nicht die Möglichkeit, eine _Application_ zuverlässig statisch zu analysieren.

Dinge, die unter den Begriff „Bewerbung“ fallen

  • PLATFORM_DIRECTIVES/PIPES/PROVIDERS
  • Dinge, die Sie zuvor zu Bootstrap() hinzugefügt haben
  • Einstellungen auf Compilerebene
  • mehrere Root-Komponenten
  • serverseitige Nutzung.

NgModules führen die Idee eines statisch analysierbaren Satzes von Merkmalen ein. Interessant ist, dass wir im AoT-Kompilierungsmodus Ihr Root-Modul analysieren und für jedes Modul in der Anwendung eine ModuleFactory _generieren_ - dies ist die vorkompilierte Version eines Moduls, das _nur_ die Factorys enthält, auf die Sie statisch in Templates verweisen, und diejenigen, die Sie selbst als "entryComponents" markieren

Da wir die für die Kompilierung erforderlichen Informationen bereits im Voraus extrahiert haben, können wir die Dekorateure tatsächlich aus dem Baum schütteln (ngc erledigt dies automatisch für das Finale) – und anstatt Ihre Anwendung zu bündeln, beginnend mit Ihrem Root-Modul, beginnen Sie in Ihrer generierten Root Module_Factory_, die nur den Code enthält, der tatsächlich in Ihrer Anwendung verwendet wird, sodass Sie keine Strafe für Modularität zahlen und Tools wie Rollup und Webpack2 effizienter arbeiten können

mehr folgt in der nächsten Antwort...

@robwormald Ich kann die Wertschätzung für diese Art von Hintergrundinformationen nicht in ein Emoji packen.

Danke schön!

Ein weiteres Problem, auf das wir gestoßen sind, das NgModules löst:

Stellen Sie sich einen Fall vor, in dem Sie einen DialogService oder ähnliches erstellen möchten.

Historisch würdest du so etwas tun:

@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);
      })
  }
}

...was Sie gerne verwenden würden

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

Was hier zu beachten ist -

  • Komponentenkompilierung im JiT-Modus _muss_ asynchron sein, wegen externer TemplateUrls und StyleUrls
  • ein viewContainer akzeptiert eine _componentFactory_ - also hat Ihr Code jetzt ein Problem: Sie müssen entweder den Code neu schreiben, um den Modus zu wechseln (zwischen JiT und AoT), _oder_ Sie müssen immer davon ausgehen, dass die API zum Einfügen von Komponenten asynchron ist. Dies mag im Fall eines Dialogs in Ordnung sein, aber wenn Sie komplexe UIs dynamisch erstellen (denken Sie an ein Dashboard oder eine Grid-Ansicht oder was auch immer), entsteht eine Menge unnötiger Promise-Planung.
  • Drittanbieter- oder gemeinsam genutzte Dienste/Komponenten (wie SharedDialogService) haben das gleiche Problem, da sie _entweder_ Komponenten oder Komponentenfabriken akzeptieren müssen

Dieses Problem tritt bei _jeder_ Anwendung auf, die dynamisches Einfügen von Komponenten durchführt (was nicht unbedingt Lazy Loading bedeutet) - Dialoge, Router usw. erwarten alle, dass sie mit ComponentTypes (den Klassen) anstelle von Selektoren (foo-bar) interagieren.

Wenn Sie also eine Komponente zu Ihrem entryComponents-Array in einem NgModule-Dekorator hinzufügen:

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

Was dies dem Compiler sagt, ist "generiere mir eine Zuordnung zwischen MyRandomDialogComponent und seiner kompilierten MyRandomDialogComponentNgFactory" und _speichere es in der NgModuleFactory, in der es deklariert ist_

Somit sieht eine NgModule-gesteuerte Version des obigen dialogService wie folgt aus:

@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);
  }
}

Jetzt kann jede Komponente, die Sie zu entryModules hinzugefügt haben, synchron abgerufen und dynamisch in die Ansicht eingefügt werden, und Ihr Code muss _nicht_ geändert werden, je nachdem, in welchem ​​Modus Sie sich befinden, noch müssen sich Drittanbieter/gemeinsam genutzte Bibliotheken um die Kompilierung kümmern Logik.

Danke für die Erklärung @robwormald

Eine Frage ist: Erfordert das die Entfernung von Richtlinien-/Pipe-Deklarationen? Gibt es einen Grund, warum sie nicht mit NgModule koexistieren können?

Ich habe das Gefühl, dass die Leute, einschließlich mir selbst, nicht über das „neue Kind auf dem Block“ NgModule oder ein Missverständnis davon frustriert sind, sondern dass die „alte Art“, Dinge zu tun, die bei vielen Leuten _gut zu funktionieren scheint, nicht mehr vorhanden ist gewaltsam entfernt werden, insbesondere in diesem späten RC-Stadium. Ich denke, dies ist ein wichtiger Unterschied zu jeglichem Widerstand gegen NgModule selbst, von dem ich nicht viel gesehen habe und der noch nicht direkt angesprochen wurde.

Ich sehe auch, dass die Pull-Anforderung zum Entfernen von Direktiven/Pipe-Deklarationen aktiv ist (https://github.com/angular/angular/pull/10912) – ich hoffe, wir können eine Antwort zu diesem Punkt erhalten, bevor etwas festgelegt wird Stein.

Vielen Dank im Voraus. Es war zweifellos eine Freude, mit Angular zu arbeiten, und ich schätze die harte Arbeit des Teams im letzten Jahr+ sehr

Hier gibt es ein paar Kommentare zum "globalen Geltungsbereich" - dies missversteht die Mechanik des Compilers und der Module (was völlig verständlich ist, das ist ein komplexes Zeug).

Das Ablegen Ihrer gesamten Anwendung in ein einzelnes NgModule ist in der Weise „in Ordnung“, wie es in Angular1 „in Ordnung“ war, den Status Ihrer gesamten Anwendung auf $rootScope abzulegen (sprich: es funktioniert, aber sein schlechtes Anwendungsdesign).

In Angular 1 hat das Einbringen eines Moduls in eine Anwendung Ihre gesamte Anwendung mehr oder weniger "verschmutzt", da alles in einen einzigen Injektorbeutel geworfen wurde.

In Angular2 verfügen NgModues über einige sehr leistungsfähige Scoping-Mechanismen, die eine Komposition ohne Verschmutzung ermöglichen. Wieder geht es zurück zum Compiler.

Wenn Angular Ihre Anwendung durchläuft und kompiliert, wird jede Komponente, auf die es trifft, _in dem Kontext kompiliert, in dem sie deklariert wurde_

Stellen Sie sich beispielsweise vor, Sie haben ein SharedModule mit einigen Funktionen, die Sie über eine Anwendung hinweg freigeben möchten

@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 {}

Sowohl SharedComponentOne als auch SharedComponentTwo sind im SharedModule _deklariert_ - Deklarationen implizieren _Eigentum_ - also gehören diese beiden Komponenten SharedModule. Allerdings wird _nur_ SharedComponentOne aus dem Modul _exportiert_ - SharedComponentTwo bleibt _privat_ für SharedModule.

Wenn Sie SharedModule einbringen und in einem anderen Modul verwenden würden, etwa so:

@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 {}

...wenn der Compiler mit dem Kompilieren SomeComponent beginnt, entdeckt er den Selektor shared-component-one und weil SharedModule (das SharedComponentOne exportiert) in SomeModule importiert wird

Wenn der Compiler SharedComponentOne tatsächlich kompiliert, tut er dies interessanterweise "innerhalb" von SharedModule, wodurch er Dinge innerhalb von SharedModule verwenden kann, die nicht der Außenwelt ausgesetzt sind.

Dies ist sehr ähnlich wie es früher mit Component.directives funktioniert hat, und in diesem Fall sind sie gleich.

Überlegen Sie jedoch, ob Sie so etwas wie eine Tabs-Funktion hätten:

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

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

Diese beiden Komponenten befinden sich auf oberster Ebene, es gibt keine hierarchische Beziehung, auf die man sich verlassen kann. Diese führten zur Explosion einer Art Versammlung von Menschen, die etwas taten

export const TAB_DIRECTIVES = [ TabsComponent, TabComponent ]

Eine kompliziertere Tabs-Funktion hat möglicherweise einen Dienst, der mehrere Instanzen von Tabs verwaltet, also müssen Sie auch diesen Fall behandeln ...

export const TAB_PROVIDERS = [ ... ]

und die Verwendung wird zu einer Übung, sich an all die Dinge zu erinnern, die Sie exportieren und importieren müssen ...

import {TAB_DIRECTIVES, TAB_PROVIDERS}

und dann all diese Dinge an der richtigen Stelle bereitzustellen, _überall_, wo Sie sie verwenden möchten. Es ist an dieser Stelle auch sehr einfach zu vergessen, ALLE Dinge zu importieren, die Sie für eine Funktion benötigen, und am Ende seltsame stille Fehler oder Komponenten zu haben, die ohne ihren gesamten erforderlichen Kontext kompiliert werden.

Mit einem NgModule können Sie sie einfach zu einer einzigen Einheit zusammenfassen und diese an Ihre Anwendung weitergeben und gegebenenfalls importieren.

Für Bibliotheken wie Material Design, die möglicherweise eine Reihe von Funktionen haben, die auf mehrere Module verteilt sind, können Sie dieselbe Import-/Exportsemantik nutzen, um sie noch portabler zu machen:

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

Das Ziehen dieses einzelnen Moduls ermöglicht es Ihrer gesamten Anwendung, Komponenten zu verwenden, und wiederum werden zur AoT-Zeit nur die von Ihnen verwendeten in den generierten Code importiert.

Warum wir Component.directives/pipes entfernt haben, haben wir viel Feedback in beide Richtungen gehört. Wir sind der Meinung, dass es im Allgemeinen ein schlechtes Muster ist, zwei Möglichkeiten zu haben, dasselbe zu erreichen, also haben wir uns dafür entschieden, es den Leuten zu ermöglichen, im Allgemeinen weniger Code zu schreiben, und diejenigen, die den expliziten Bereich wünschen, der zuvor von Component.directives angeboten wurde, können die _gleiche_ Funktionalität erreichen Umfang auf Modulebene.

In RC5 haben wir eine Art automagisches Heben von Component.directives in den "globalen" Geltungsbereich durchgeführt. Dies war ein Versuch, den Übergang zu glätten, und obwohl es für die meisten Leute funktionierte, verursachte das gemischte Alt-und-Neu-Verhalten einige seltsame Fehler und Verhaltensweisen, die zwar frustrierend, aber vorübergehend sind. Dies verschwindet in RC6 (und Fehlermeldungen wurden verbessert)

Warum sich das so spät im Spiel geändert hat, dafür können wir uns nur entschuldigen. Wir mögen Änderungen in letzter Minute nicht mehr als jeder von Ihnen. Am Ende des Tages bauen wir buchstäblich ein Framework auf eine Weise, die noch nie zuvor im Frontend-Land gemacht wurde, und daher werden wir auf unerwartete Probleme und Designprobleme stoßen. Dies war einer dieser Fälle, und er wurde im Kernteam heftig diskutiert und untersucht, bevor wir die Entscheidung trafen. Nochmals, wir entschuldigen uns für die Unannehmlichkeiten, aber wir sind zuversichtlich, dass das Nettoergebnis eine viel schönere Art ist, _Anwendungen_ zu erstellen, weshalb wir alle hier sind.

Danke für die Geduld aller. Ich lasse dies offen, wenn es andere Fragen gibt, die ich hier nicht behandelt habe.

rauben

Gute Arbeit, @robwormald

Ich möchte noch ein paar Beobachtungen anfügen:

Anbieter

Rob konzentrierte sich auf _Deklarationen_, _Importe_ und _Exporte_. Modul _Anbieter_ sind unterschiedlich.

@Component.providers lebt! Nur @Component.directives und @Component.pipes verschwinden.

Sie können sowohl @NgModules.providers als auch @Component.providers verwenden. Sie haben unterschiedliche Zwecke:

a) @NgModules.providers _erweitert_ die Anwendung durch Hinzufügen von Anbietern zum "Haupt"-Injektor (dem App-Root-Injektor für eifrig geladene Module). So fügt RouterModule Ihrer App einen Routing-Dienst hinzu, ohne dass Sie ihn bereitstellen müssen.

b) @Component.providers _kapselt_ die Dienstbereitstellung innerhalb des Bereichs der Komponenteninstanz (und ihres Komponentenunterbaums) ein.

Beide Ansätze erfüllen unterschiedliche Anforderungen.

Mein allgemeiner Ratschlag: _wenn Sie heute einen Anbieter auf @Component haben, lassen Sie es dort_

Funktionsmodule

Sie sind eine leistungsstarke Möglichkeit, Ihre App zu organisieren. Das Kapitel zum Angular-Modul enthält einen kurzen Abschnitt zum Refactoring von einem monolithischen Angular-Modul zu einem Feature-Modul . Es ist ziemlich einfach (zumindest war es für mich so, als ich es mehrmals gemacht habe.).

Ich suche in meiner App nach natürlichen Nähten. Ich werde nicht verrückt. Ich modularisiere nicht jede Komponente.

Der Grund, warum Material Design dies zu tun scheint, ist, dass sie versuchen, es uns einfacher zu machen, das, was wir wollen, auf feinkörnige Weise zu verwenden.

Sie werden ein Küchenspülenmodul haben, das einfach alles wieder exportiert. Das könntest du einfach importieren und fertig. Aber wenn ich meine eigene App optimiere, erstelle ich ein ähnliches _Re-Exporting-Modul_, das nur die MD-Teile exportiert, die ich möchte.

Dies ist ein Muster, dem jeder Bibliotheksanbieter folgen könnte und das in Unternehmen sinnvoll sein könnte, in denen wir unsere eigenen vom Unternehmen genehmigten "Kits" mit genehmigten Spielereien zusammenstellen.

Erkennen von Deklarationsabhängigkeiten

Der Compiler kann Ihnen jetzt viel besser mitteilen, wenn etwas fehlt. Wenn Sie die empfohlene Vorgehensweise befolgen und Ihre Komponentenselektornamen _immer, immer, immer_ mit Bindestrich trennen, wird Ihnen der Compiler mitteilen, wenn Sie eine nicht deklarierte Komponente haben. Es erfasst auch nicht deklarierte/nicht erkannte Datenbindungen und Anweisungen.

Die Migration von vor RC5 fördert ein Gefühl des Verlustes. Wir müssen die mühsame Arbeit machen, Abhängigkeiten in unseren vorherigen directives - und pipes -Listen zu entdecken. Und wir müssen deduplizieren. Das ist die wesentliche Unannehmlichkeit des Lebens am Abgrund.

Ein RC sollte sich nicht so stark verändern

Jep. Da bekommt man vom Team keine Einwände. Es war keine Absicht. Hätten wir gewusst, dass wir NgModule brauchen, hätten wir es in der Betaversion gehabt.

Aber meiner Meinung nach ist es besser, das richtige Produkt zu liefern, als sklavisch einer Vorstellung davon zu folgen, was ein RC sein sollte, und das falsche Produkt zu liefern. Außerdem ... und es ist nicht sehr tröstlich, das zu sagen ... aber wenn Sie in letzter Zeit einige andere große Softwareunternehmen beobachtet haben, ist Ihnen vielleicht ein ebenso flexibler Begriff von "Release Candidate" aufgefallen. Das ist aus irgendeinem Grund der Weg in unserer Branche.

Ich habe jetzt eine Reihe von Apps konvertiert und anderen dabei geholfen. Sobald die „_sie haben meinen Käse (wieder) verschoben_“-Phase hinter sich gelassen haben, ist es eine ziemlich mechanische Migration und jeder scheint zu glauben, dass er an einem besseren Ort ist. Vielleicht sind sie nur nett zu mir. OTOH, ich hänge nicht mit Leuten ab, die so nett sind ;-)

(auch zu: der Name)
Wir haben Namen zu Tode geradelt. Sie wurden ursprünglich als AppModule bezeichnet (da sie etwas Höheres als eine Komponente beschreiben, eine „App“), aber dieser Begriff war nicht weit genug gefasst. Pakete, Bündel, Fässer, Globs usw.

Denken Sie daran, dass es kein Ersatz für ES-Module ist - es ist eine Erweiterung, die das Baumschütteln und ES-Module für alle Winkelentwickler besser funktionieren lässt, und semantisch ähneln sie der Funktionsweise von ES-Modulen (Importe, Exporte, Deklarationen).

Daher ist die Namensfindung schwierig. NgModul ist es.

Wir sind API-komplett für 2.0.0 und werden daher die nächsten Monate nach der Veröffentlichung beobachten, um zu sehen, welche Muster sich entwickeln und wo wir bessere Schlüsse für 2.1 ziehen können.

Vielen Dank @robwormald @wardbell für die sehr aufschlussreichen Kommentare. Ich denke das ist für mich die größte Erleichterung

„Wir sind API-komplett für 2.0.0, und deshalb werden wir die nächsten Monate nach der Veröffentlichung beobachten, um zu sehen, welche Muster sich entwickeln und wo wir bessere Schlussfolgerungen für 2.1 ziehen können.“

Es ist etwas, das wir bereits vor ein paar Wochen gehört haben, aber jetzt speziell im Zusammenhang mit NgModules zusammen mit all diesem Feedback. Es ist das Vertrauen, das ich brauchte, um zu einem Vorstand zu gehen und zu sagen. Wir sind hier fertig, Zeit, die Erstellung unserer Anwendung abzuschließen. Ich möchte auch dem gesamten ng2-Team und der Community meine Glückwünsche zum Erreichen dieses Meilensteins aussprechen! Spannende Zeiten stehen bevor.

Ich glaube ehrlich, dass man das sagen kann @SaltyDH. Die Abwanderung von Angular 2 ist vorbei.

Das bedeutet nicht, dass Angular 2 mit der Entwicklung fertig ist. Es wird zukünftige Versionen geben. Aber die Abwanderung zu 2.0 ... ist ... vorbei!

Vielen Dank für die Ehrlichkeit und die expliziten Anwendungsfälle, Leute. Es hilft wirklich.

Nur ein kurzer Gedanke zur Benennung und Duplizierung in der API für NgModule, was meiner Meinung nach etwas umständlich ist.

IMO das:

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

...könnte klarer und prägnanter sein als:

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

1) WRT zur Benennung (öffentlich und privat vs. Deklarationen und Exporte), es ist im Wesentlichen wie @robwormald oben und ich bin sicher, dass viele andere es erklären

2) (Ignoriert die Namensgebung) warum sollte SharedComponentOne wiederholt werden? Sicherlich könnte man sagen, wenn es sich um einen "Export" handelt, muss es sich um eine "Anmeldung" handeln, also könnte es einfach so entzuckert werden?

Nur meine zwei Cent zu etwas sehr Subjektivem 😄 - nochmals vielen Dank für die ausführlichen Erklärungen!

@robwormald @wardbell Danke für die ausführlichen Erklärungen.

Und wie ich schon früher in diesem Thread sagte, NgModules helfen uns, uns besser zu organisieren. Ein aktuelles Beispiel ist das Erstellen von Validator-Direktiven für vorlagengesteuerte Formulare. Vor RC5 mussten wir jede Anweisung in die Komponente importieren, in der wir ein Formular erstellen. Jetzt packen wir es einfach in VaildatorModule und importieren das Modul, wo immer es erforderlich ist. Jeder Validator, den wir später hinzufügen, ist automatisch für die Module verfügbar, in die ich ValidatorModule importiert habe. Ich muss nur die Vorlage aktualisieren, ohne mich um Abhängigkeiten kümmern zu müssen.

@JamesHenry declarations , imports und exports werden verwendet, um NgModule in Einklang mit ES6-Modulen zu halten, wie wir import , export und declare Zeug in ES6-Modulen.
Ich stimme dem Zuckern zu, Dinge, die exportiert werden, können auf magische Weise in Deklarationen entzuckert werden.

@JamesHenry

1), sind wir bei Imports/Exports geblieben, weil das mentale Modell näher an der Funktionsweise von es-Modulen liegt (zumindest in Bezug auf den Geltungsbereich) – Sie deklarieren Dinge in einem Modul, importieren Dinge aus anderen Modulen und exportieren Dinge, um sie verfügbar zu machen Andere.

2) if it is an "export" it must be a declaration, so it could just be desugared that way? -> Dies funktioniert, bis Sie ein ngModule zum erneuten Exportieren verwenden, wie im obigen MaterialModule-Beispiel - es gibt viele Fälle, in denen Sie ein ngModule verwenden können, um etwas, das in einem anderen Modul deklariert ist, erneut zu exportieren, und dann fallen die Schlussfolgerungen irgendwie auseinander.

@robwormald Tolle Kommentare! verdient auf jeden Fall einen Blogbeitrag.

Ich habe eine Dialogbibliothek , die jetzt @NgModule verwendet, und ich kann sagen, dass ich sehe, dass Benutzer beim Versuch, benutzerdefinierte Komponenten hinzuzufügen, Probleme haben, da sie vergessen, sie in entryComponents zu registrieren. Dies ist jedoch anscheinend nicht klar genug Verständlich, da es sich um eine erweiterte Funktion handelt ...

Ich bin mir sicher, dass sich das mit der Zeit einpendeln wird

@shlomiassaf danke!

Sollte für Fälle wie Ihren auch erwähnt werden:

Beachten Sie, dass Sie bei Verwendung des Routers von angle Komponenten zu Deklarationen und der Routenkonfiguration hinzufügen, aber _nicht_ zu entryComponents, obwohl der Router die eigentliche Definition von entryComponents ist. (Denken Sie daran - entryComponent === Ding, auf das Sie sich mit der Klasse beziehen möchten, und nicht mit dem Selektor)

Es gibt einen coolen Trick, den jede Bibliothek nutzen kann – es gibt ein magisches Token namens ANALYZE_FOR_ENTRY_COMPONENTS – siehe https://github.com/angular/angular/blob/master/modules/%40angular/router/src/ router_module.ts#L117 für die Verwendung durch den Router.

Für Bibliotheken, die sich mit dynamisch eingefügten Komponenten befassen, könnten Sie also Folgendes tun:

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

verwendet wie

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

Könnte für Ihren Anwendungsfall funktionieren, möglicherweise nicht.

@JamesHenry Sehr wichtig, dass declarations nicht mit private verwechselt wird. Sie sagen _Dieses Modul deklariert diese Komponente_. Sie machen keine Aussage über öffentlich oder privat. Sie erheben einen Eigentumsanspruch.

Es ist wirklich so, wie es in ES6-Modulen passiert. Alles, was Sie in der Datei definieren, "gehört" zu dem von dieser Datei definierten Modul. Ob es öffentlich ist oder nicht, hängt von Ihrer Verwendung des Schlüsselworts export ab.

Und wie bei ES6-Modulen können Sie importierte Inhalte _re-exportieren_.

Ich stelle mir declarations gerne als den "Trick" vor, der mich davon abhält, alle meine Komponenten, Direktiven und Pipes physisch in derselben physischen Datei zu platzieren (wie Sie es mit ES6-Modulen tun müssten, wenn Sie dies beabsichtigten dass alle diese Klassen zum selben ES6-Modul gehören).

Für mich ist declarations also ein Ersatz für das Einfügen dieser Dateien in eine schrecklich große Datei. Das ist sowieso _mein_ mentales Modell.

Zu beachten ist der logische Unterschied zwischen Anbietern und Komponenten im Kontext eines Moduls.

Anbieter und Komponenten werden an derselben Stelle deklariert ( NgModuleMetadataType ), sodass ein Entwickler möglicherweise intuitiv das Gefühl hat, dass sich Anbieter wie Komponenten verhalten ... was bedeutet, dass ein Anbieter in einem Modul zu einer Instanz für dieses Modul führt. .

Da die Provider von der DI verwaltet werden, stimmt dies natürlich nicht, sie sind eigentlich Anwendungsebene.
Komponenten in einem Modul sind privat, wenn sie nicht exportiert werden, dies könnte zu Verwirrung führen.

Ich liebe das Konzept von Modulen, meiner Meinung nach besteht das einzige Problem in der API darin, dass Anbieter und Komponenten an derselben Stelle innerhalb eines Moduls deklariert werden ... für Neueinsteiger ist es schwer zu verstehen.

@wardbell Danke Ward das ist wirklich super! Nur zur Klarstellung, da dies gerade in Diskussionen aufgekommen ist, wenn wir sagen, dass Angular 2 die API vollständig ist, über welche Namespaces sprechen wir hier? @eckig/???

@robwormald Danke! Ein toller Tipp!!!
Eine mit Zuckergeschmack! umsetzen wird.

Ich bin kein Google-Angestellter und vielleicht kann ein Google-Angestellter das nicht sagen. Ich kann nur berichten, was ich mit eigenen Augen sehe: ein sehr ernsthaftes Einfrieren der API in den Bibliotheken von @angular/ .

Es gibt gute Ideen, die im Regal liegen, weil sie nicht gut genug oder tiefgreifend genug waren, um das Anhalten der Veröffentlichung zu rechtfertigen. So sollte es sein. Gute Ideen hören nie auf. Aber es ist an der Zeit zu sagen: _Das ist dein Angular 2.0_.

Wir haben die versprochene Entfernung der veralteten API zwischen jetzt und "endgültig". Das hat Tweaks ... wie jeder sehen kann, wenn er sich Master ansieht. Ich habe das Gefühl, dass wir fertig sind.

@wardbell Ich wiederhole, was Sie über Exporte sagen.
Die index.ts wurde einmal mit gefüllt

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

ist jetzt auf nur export * from my.module reduziert
rest all stuff clean sitzt in NgModule exports as
exports: [ AComponent, BComponent, CComponent, PDirective ] und so weiter

@wardbell Ich denke, @NgModules.providers hätte @NgModules.rootProviders oder @NgModules.appProviders sein sollen.

Ich denke, es beschreibt klar den Kontext der Anbieter.

@shlomiassaf Das wäre irreführend. Die Wirkung von @NgModules.providers ist für eifrige und faule Module unterschiedlich. Faul geladene Module bekommen ihren eigenen untergeordneten Injektor, was bedeutet, dass _ihre Anbieter_ zum _untergeordneten_ Injektor hinzugefügt werden, nicht zum _root_-Injektor. Und so geht es, wenn ein Fauler einen Faulen belädt.

Vielleicht hätte es auch einen anderen Namen geben können. Sie wissen, wie _das_ geht. Aber rootProviders wäre aus den eben genannten Gründen keine Verbesserung gewesen.

@wardbell stimmte zu, dachte nicht an dieses Szenario.

Ich wollte nur das Gefühl verstärken, dass die gründlichen Antworten und die Kommunikation sehr geschätzt werden. Wenn dies tatsächlich die letzten Wachstumsschmerzen vom RC zum Finale sind, dann sind wir auf dem Weg zu den Rennen. Danke!

Wie andere angemerkt haben, wird das Feedback des Teams geschätzt. Diese Art von Änderung während dieser Entwicklungsphase weist jedoch auf grundlegende Konstruktionsfehler hin.
Seien wir ehrlich zu uns selbst, wir alle haben diese Art von Fehlern gemacht, also hat es keinen Wert, wertend zu sein, aber wenn ich einen Fehler mache, demütigt es mich und macht mich anschließend hoffentlich vorsichtiger. Ich habe nicht den Eindruck, dass es die gleiche Wirkung auf das Team von Anagular hat.

Ich betrachte Deklarationen gerne als den "Trick", der mich davon abhält, alle meine Komponenten, Direktiven und Pipes physisch in derselben physischen Datei zu platzieren (wie Sie es mit ES6-Modulen tun müssten, wenn Sie alle diese Klassen beabsichtigen gehören zum selben ES6-Modul).

Für mich sind Deklarationen also ein Ersatz dafür, diese Dateien in eine schrecklich große Datei einzufügen. Das ist sowieso mein mentales Modell.

@wardbell Vielleicht fehlt mir etwas Grundlegendes, aber ich sehe nicht, wie sich die Verwendung NgModule.declarations grundlegend vom Importieren aller, aber nur dem erneuten Exportieren einiger Ihrer ESModule unterscheidet. Ironischerweise besteht die primäre Einschränkung von ESModules darin, dass sie nur das Konzept physischer Module bereitstellen, nicht logischer. Ich sehe nicht, wie NgModule das verbessert. Es handelt sich lediglich um eine andere Aggregationssyntax, die jedoch die Abstraktionsebene nicht auf ein sinnvolles Maß anhebt.

Außerdem lösen NgModule ein großes Problem nicht vollständig:

Das ganze Function[] -Muster ist auf die falsche Weise undurchsichtig. Es senkt die Auffindbarkeit auf null. Man muss die Quelle lesen, um festzustellen, was in einer Reihe von Anbietern enthalten ist. Dasselbe gilt für NgModule.exports .

Aber meiner Meinung nach ist es besser, das richtige Produkt zu liefern, als sklavisch einer Vorstellung davon zu folgen, was ein RC sein sollte, und das falsche Produkt zu liefern. Außerdem ... und es ist nicht sehr tröstlich, das zu sagen ... aber wenn Sie in letzter Zeit einige andere große Softwareunternehmen beobachtet haben, ist Ihnen vielleicht ein ebenso flexibler Begriff von "Release Candidate" aufgefallen. Das ist aus irgendeinem Grund der Weg in unserer Branche.

@wardbell Die größte Frustration über RC ist für mich der Eindruck, dass eine Beta gerade wegen ng-conf und google i/o auf RC gepusht wurde. Um Fortschritte zu erzielen, sollte der Grund klar formuliert werden: Es war _Marketing_, und als Technologen sollten wir den Trend dieser flexiblen Vorstellungen von Reife bekämpfen. Sie kennen vielleicht einen bekannten Autohersteller im Tal, wo die Diskussion darüber dreht, ob es richtig war, eine Beta für ein Produkt zu verkaufen, weil es ein Leben gekostet haben könnte. Ich will nicht übertreiben, aber als Technologen müssen wir uns zu Wort melden, wenn sich unsere Branche so entwickelt, denn dann geht sie in die falsche Richtung.

Ich mag den ngmodule-Ansatz, aber ich habe eine Frage @robwormald :

Ich habe einen gemeinsam genutzten Dienst, der keine Komponenten, keine Anweisungen und keine Pipes hat. Es hat nur Dienste ( forRoot ) und enthält alle Geschäftsmodellklassen. Das app.module importiert ServerApiModule.forRoot() , daher sind die Dienste für die gesamte Anwendung verfügbar. Sollen die Funktionsmodule, die die Dienste und Geschäftsmodellklassen verwenden, dieses gemeinsam genutzte Modul importieren? Technisch ist es nicht notwendig (keine Fehler), aber aus semantischer Sicht wäre es sinnvoll (ebenfalls keine Fehler). Was sollen wir mit solchen Modulen machen? Importieren oder nicht? Ich persönlich mag die zweite Möglichkeit, weil sie besagt: „Hey, ich bin ein Feature-Modul und ich brauche diese Dienste und ich brauche diese Geschäftsmodellklassen“.

Danke für eine Antwort!

Ich kann also den Schmerz mit Bibliotheken/modularen Anwendungsbibliotheken und ngModule spüren.

Aber wie gesagt, vermische nicht zwei mögliche Wege. Das ist und wird verwirrend sein.

Der richtige Ansatz wäre also, für jede Komponente ein ngModule zu deklarieren.
Da dies jedoch für jede Komponente viel mehr Kesselcodierer bedeutet, funktioniert dieser Weg auch nicht im großen Maßstab.

Fügen Sie also auf keinen Fall einen neuen Dekorator namens ComponentModule hinzu, der mehr oder weniger Zucker ist, um zu vermeiden, dass Komponenten und Module wie Material deklariert werden müssen.

Weg so? Wenn ich eine Komponente sehe. Ich weiß, dass es Teil eines ngModule sein MUSS. Wenn ich einen Fall für viele Komponenten habe, um sie zu bündeln, KANN ich NgModule verwenden. Wenn ich nur eine eigenständige Komponente wie die "alten Komponenten" möchte, verwende ich das ComponentModule und KENNE alle Abhängigkeiten und dass es eine Modulabhängigkeit für andere Module sein kann, aber nicht Teil davon ist

@nathraQ Wenn der richtige Ansatz darin besteht, NgModule für jede Komponente zu verwenden, und dies kann durchaus der Fall sein, hätte NgModule nicht eingeführt und die Komponente nur verbessert werden sollen. In Bezug auf Boilerplate ist Angular 2 so schwerfällig, dass es an dieser Stelle kaum eine Rolle spielt.

Viele Frameworks, die kein eigenes Modulsystem haben, haben sehr erfolgreich Konventionen verwendet, um Standardmuster für das Layout und die Sichtbarkeit von Konstrukten zu etablieren. Ein weiser Mann hat einmal gesagt, dass man Konventionen nicht nachträglich definieren kann; dass sie von Anfang an dabei sein müssen. Ich war skeptisch gegenüber dieser Behauptung, aber dieses Debakel beweist, dass er Recht hatte.

@aluanhaddad Entschuldigung, ich bin anderer Meinung. Ich hatte meine Anwendungsfälle für nur ein Modul in Angular 1.x mit benutzerdefiniertem Abhängigkeitsmanagement (wie der Starter dieses Threads), aber ich hatte auch Anwendungsfälle für Module, um eine Reihe von Controllern, Anweisungen und Diensten zu bündeln.

Beides ist nützlich. Jetzt müssen wir herausfinden, wie wir es für alle verständlich integrieren können

Wow, das war eine lange Lektüre :smile:

Ich kann die Vor- und Nachteile der neuen Änderung sehen, aber es hat mich dazu gebracht, über ein Szenario nachzudenken, mit dem ich in Angular 1 Probleme hatte.

@wardbell @robwormald -

Wenn ich das SharedModule-Muster verwende und zwei Bibliotheken von Drittanbietern (ui-bootsrap vs. angle-strap jemand?) importiere, die beide denselben Selektor für eine Komponente verwenden, sagen wir my-selectbox

Ich erhalte eine Fehlermeldung, wenn ich versuche, beide zu importieren? Rechts?

Eine Lösung, die ich hier gelesen habe, besteht darin, eine der Bibliotheken in einem benutzerdefinierten Modul erneut zu exportieren
Aber das bedeutet, dass ich das Wrapper-Modul jedes Mal aktualisieren muss, wenn die Bibliothek aktualisiert wird, nein?

Außerdem kann es vorkommen, dass ich meinen eigenen Komponentenselektor mit demselben Namen habe (und in großen Projekten kann dies mehr als einmal vorkommen).

Gibt es eine empfohlene Lösung für dieses Problem? oder ist es das "Wrapper-Modul"?
(Ich hoffe, wir werden nicht auf die Verwendung eines Präfixes für Selektoren zurückkommen, das war kein Spaß)

Vielen Dank im Voraus!

Namensräume oder Präfixe, wie manche es nennen, sind im Allgemeinen eine gute Idee, egal wie groß Ihr Projekt ist. Ja, es mag in kleineren Projekten trivialer sein, aber sobald Module von Drittanbietern beteiligt sind, würde ich sagen, dass es fast eine Voraussetzung ist – zumindest bietet es die Gewissheit, dass es nicht zu Kollisionen kommt, selbst wenn andere Module aktualisiert werden , aber auch Entwickler können leicht erkennen, was zu jedem Modul gehört, ohne unbedingt dem Abhängigkeitsbaum folgen zu müssen.

@nathraQ Alle diese Muster können mit ECMAScript-Modulen erreicht werden. Die Einführung von NgModule bringt uns nicht weiter und die Tatsache, dass Bibliotheken wie AngularMaterial Komponenten in NgModule umwandeln, nur um die zuvor bereitgestellte Kapselung beizubehalten, beweist nur den Punkt.

@aluanhaddad NgModules versucht etwas ganz anderes als ES-Module und ersetzt auch nicht die Komponentenkapselung, dh sowohl ES-Module als auch Komponenten haben ihre Kernaufgaben nicht geändert. NgModules ist das Medium, durch das Sie die Architektur in Ihrer gesamten Anwendung beschreiben, und dies hilft Angular, Ihre Absicht besser zu verstehen und entsprechend zu optimieren, was Dinge wie das vorherige Kompilieren bestimmter Teile Ihrer Anwendung, das Bereitstellen dynamisch aufgelöster Module von einem Server usw. ermöglicht davon mit ES-Modulen nicht erreichbar. Aus den gleichen Gründen ist ein NgModul pro Komponente nicht die Faustregel.

Es ist wahr, dass einfachere Anwendungen möglicherweise nicht so sehr von diesen Vorteilen profitieren, aber in diesen Fällen sollten NgModule sowieso weniger "lästig" sein.

@emilio-martinez , wie @aluanhaddad schrieb, ES6 und der "alte eckige 2-Wege" gaben uns den Namensraum, den wir brauchten.

Ich habe mit Angular 1 an sehr großen Projekten gearbeitet, wobei ein Selektor namens: mb-product-list sehr schnell mit anderen kollidieren kann, wenn es sich um ein großes Projekt handelt (sogar in einem Team von mehr als 5 Entwicklern).

Wenn Sie versuchen, es mit mehr Namensräumen zu lösen, erhalten Sie am Ende: mb-somefeature-product-list , was die Vorlagen schmutzig aussehen lässt.

Ich war sehr froh zu sehen, dass es wegen der Metadaten von directives in ng2 gelöst wurde.
Sie können jedes beliebige Paket mit npm installieren und nur das importieren, was Sie pro Komponente benötigen.

ngModules hat seine Vorteile, das ist sicher, es hilft beim asynchronen Laden von Chunks und hilft uns auch, weniger Importe zu schreiben und die Produktivität zu verbessern.

Aber die Verwendung des Musters SharedModule führt einen globalen Namespace ein, ähnlich wie wir es in ng1 hatten.

Zumindest bei Providern ist es durch das ES6-Token, den Dateispeicherort, benannt.

Bei Komponenten wird es wegen der Selektoren schreien, dass es zwei Komponenten mit demselben Selektor gibt.

Ich wünschte, wir hätten eine einfache Möglichkeit, einen speziellen Namensraum für Anwendungsfälle von Kollisionen mit Drittanbieter- oder lokalen gemeinsam genutzten Komponenten zu konfigurieren.

So etwas wie "Selector Override".

Das habe ich gefragt

Danke @robwormald für deinen detaillierten Einblick, aber eines von Neulingen wie mir (meistens bin ich ein Backend-Entwickler). Ich lerne Angular 2 und mit Typoskript. Das ES6-Modulkonzept ist mir also etwas verschwommen
Wir haben eine komplexe Bewerbungsstruktur. Es ist eine Analyse-App, bei der meine Komponentenanzahl fast 60 beträgt.
Und ich denke, es ist unter RC4 gut strukturiert. Abgesehen von Login haben wir keinerlei Routing verwendet, da routern die gesamte Komponente nachbildet. Also planen wir eine Tab-basierte App. Es gibt zwei Haupt-Tabs (1. Analyse 2. Dashboard).
Die Registerkarte „Analytics“ enthält mehrere Registerkarten, die jeweils eine einzelne Analyse enthalten. Dashboard wird auch haben
mehrere Registerkarten, aber jede Registerkarte besteht aus mehreren Analysen, unter denen gespeichert wurde
der Analytikbereich. Gehen Sie also von mehreren Registerkarten (sowohl unter Dashboard als auch unter Analyse) hin und her.
und auch beim Wechseln zwischen Dashboard-Tab und Analytics-Tab, glauben wir, dass Routing nicht funktioniert
unser Zweck (korrigieren Sie mich, wenn ich etwas Dummes sage).
Jetzt macht das RC5 NgModule unsere Anwendung kaputt. Wir wissen wirklich nicht wie
unsere Anwendung neu gestalten. Können wir die AoT-Kompilierung wirklich in unserer Anwendung verwenden? Ist nicht
das ganze AoT-Ding basiert auf Routing?

@shairez NgModules bieten genau diese Art von Namensraum. Lassen Sie mich versuchen, dies etwas näher zu erläutern ...

Das Wichtigste, was hier zu erkennen ist, ist, dass eine Komponente mehr oder weniger "innerhalb" des Moduls kompiliert wird, in dem sie deklariert ist - siehe https://plnkr.co/edit/9w10b1Y8Bjr5DDIxOwnC?p=preview für ein Beispiel.

Beachten Sie, dass es zwei widersprüchliche Selektoren gibt ( my-generic-selector ) - jedes der Feature-Module importiert einen davon und kann ihn intern in diesem Modul verwenden, ohne "globale" Namespaces zu verunreinigen.

So verwendet wie

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

erweitert sich zu

<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>

ohne Konflikte, denn wenn der Compiler Merkmal eins und Merkmal zwei kompiliert, tut er dies _im Kontext des Moduls, zu dem sie gehören_, wodurch vermieden wird, einen globalen Geltungsbereich zu verunreinigen.

@robwormald Sicher, das ist großartig und in diesem Sinne besser als Angular 1.

Der Anwendungsfall, über den ich geschrieben habe, bezog sich auf das Muster der Verwendung eines globalen SharedModule, wie in der Dokumentation vorgeschlagen.

Wenn ich versuche, sowohl GenericSelectorFeatureOne als auch GenericSelectorFeatureTwo innerhalb von SharedModule zu deklarieren, bekomme ich eine Fehlermeldung, richtig?

Oder wenn SharedModule eine ganze Menge nützlicher gemeinsamer Komponenten hat und ich sie in jedes Feature-Modul importieren möchte.

Wenn mein Feature-Modul einen kollidierenden Selektor hat oder ein Drittanbieter einen kollidierenden Selektor mit einer der vorhandenen Bibliotheken hat, die in SharedModule exportiert wurden, wird ein Fehler ausgegeben, richtig?

@shairez Ich denke, die meisten Anwendungen werden mit einer Reihe von "SharedModules" enden, und die Wahrscheinlichkeit von Kollisionen ist gering - Module sind billig, daher fallen keine großen Kosten für viele an.

Wenn Sie Ideen zur Verbesserung der Dokumentation haben, wäre eine PR gerne willkommen.

Danke, das ist die Antwort, die ich gesucht habe, ich werde es ausprobieren.

Ich habe noch keine besseren Ideen, wie ich das mit der neuen Art des Schreibens von Modulen lösen könnte, deshalb habe ich es hier gefragt, aber sobald ich die Lösung mit mehreren gemeinsam genutzten Modulen getestet habe, habe ich mehr Material, um darüber zu diskutieren @ wardbell und reichen Sie eine PR ein.

Danke für die Hilfe @robwormald !

In den neuesten Dokumenten, die auf https://angular.io verfügbar sind, gibt es _viele_ Warnungen zu Anti-Mustern und Fehlern, die leicht auftreten können, wenn NgModule s falsch zusammengesetzt sind. Beispielsweise

Geben Sie in einem gemeinsam genutzten Modul keine App-weiten Singleton-Anbieter an. Ein verzögert geladenes Modul, das dieses gemeinsam genutzte Modul importiert, erstellt eine eigene Kopie des Dienstes.

Das ist ziemlich beunruhigend. Wenn Sie dem erprobten und wahren Ansatz von _zuerst dafür sorgen, dass es funktioniert, dann schnell_, müssen Sie wahrscheinlich anpassen, welche Module eifrig oder träge geladen werden, basierend auf empirischen Metriken und der entstehenden Struktur dieser Module, wenn Ihre Anwendung oder Bibliothek erweitert wird. Warum sollte sich ein Modul im Grunde darum kümmern, ob es träge oder eifrig geladen wird?

Ein weiteres, scheinbar schwerwiegenderes Problem ergibt sich aus der Gegenüberstellung der folgenden Abschnitte der Dokumentation

Angenommen, ein Modul erfordert ein angepasstes HttpBackend, das einen speziellen Header für alle HTTP-Anforderungen hinzufügt. Wenn ein anderes Modul an anderer Stelle in der Anwendung ebenfalls HttpBackend anpasst oder lediglich das HttpModule importiert, könnte es den HttpBackend-Anbieter dieses Moduls überschreiben und den speziellen Header verlieren. Der Server wird HTTP-Anfragen von diesem Modul ablehnen.
Vermeiden Sie dieses Problem, indem Sie das HttpModule nur in das AppModule, das Stammmodul der Anwendung, importieren.

Kann ich Klassen und Module erneut exportieren?
Absolut!
Module sind eine großartige Möglichkeit, Klassen aus anderen Modulen selektiv zusammenzufassen und sie in einem konsolidierten, praktischen Modul erneut zu exportieren.
Ein Modul kann ganze Module erneut exportieren, wodurch effektiv alle ihre exportierten Klassen erneut exportiert werden. Angulars eigenes BrowserModule exportiert einige Module wie folgt:
Exporte: [CommonModule, ApplicationModule]
Ein Modul kann eine Kombination aus seinen eigenen Deklarationen, ausgewählten importierten Klassen und importierten Modulen exportieren.

Einerseits raten die Dokumente Benutzern davon ab, bestimmte Module erneut zu exportieren, während sie gleichzeitig erklären, dass dies eine große Bequemlichkeit bietet.

Das Konzept von NgModule Re-Exporten ist analog zu dem von ES Module Re-Exports, außer dass Sie weniger Kontrolle haben. JavaScript hat einen statischen Bereich (ja, ich weiß, dass this das nicht ist) und das ist eine seiner größten Stärken, da es eine extrem flexible Komposition und das Verbergen von Informationen ermöglicht. JavaScript unterstützt auch Shadowing, sodass Sie immer eine Möglichkeit haben, einen Bereich zu überschreiben.

Das größte Problem ist jedoch, dass sich die Beispiele in den Richtlinien alle darum drehen, wie die @angular/* Framework-Module importiert werden. Diese sind natürlich so aufteilbar, dass Konflikte intuitiv vermieden werden können. Dies liegt daran, dass sie existieren, um Dienste auf Infrastrukturebene bereitzustellen, die sich im Allgemeinen nicht überschneiden. Benutzerdefinierte Module können sich über viele Ebenen erstrecken und möchten möglicherweise eine Vielzahl von Verhaltensweisen verbessern oder ändern. Beispielsweise möchte ein Protokollierungsmodul möglicherweise Zugriff auf die Dienste Router und HTTP, während es gleichzeitig mehrere Komponenten zum Anzeigen von Informationen für Administratoren bereitstellt und eines der Formularmodule verwendet, um sie zu definieren.

Die Dokumente sagen nichts darüber aus, ob Re-Exporte transitiv sind ... Modul A re-exportiert CommonModule. Modul B re-exportiert Modul A. Modul C importiert Modul B. Bedeutet das, dass Modul C nun Direktiven von CommonModule verwenden kann?

@Martin-Wegner Sie sind transitiv wie hier beschrieben https://angular.io/docs/ts/latest/cookbook/ngmodule-faq.html#! #q-re-exportieren

@aluanhaddad wo? Ich kann kein Wort über transitive Wiederausfuhren mit mehr als einem Hop finden ...

Wenn ich lese, was @aluanhaddad aus den Dokumenten von Angular geholt hat, habe ich das Gefühl, dass ich alles überdenken muss, was ich über Angular 2 gelernt habe, und vielleicht sogar, wenn es kein Framework gibt, das Abhängigkeiten besser handhabt.

So wie ich es verstehe. Wenn ich ein App-Modul habe, das HttpModule importiert, und ich ein Funktionsmodul mit einem Dienst habe, der den Http-Dienst verwendet, sollte ich HttpModule nicht auf Funktionsmodulebene, sondern auf App-Modulebene importieren. Was passiert also, wenn ich ein Funktionsmodul erstelle, das von vielen App-Modulen gemeinsam genutzt wird? Ich muss wirklich darauf achten, dass HttpModule im App-Modul importiert wird. Ich kann nicht sagen, dass mein Feature-Modul vom HttpModule abhängt. Das ist wirklich hässlich und bedeutet, dass der NgModule-Definition viele Funktionen wie zum Beispiel PeerDependecies fehlen.
Oh Junge. Es fühlt sich an, als würde Angle 2 auseinander brechen. Ich fürchte, es ist an der Zeit, von vorne zu beginnen, Winkel 2 aufzugeben und mit Winkel 3 zu beginnen.

Es hat tatsächlich so viel Sinn in dem, was Sie gerade gesagt haben. Ich habe damit angefangen
Angular2 ist seit letztem Jahr unterwegs und hatte keinen Grund, sich geschlagen zu fühlen
trotz all der bahnbrechenden Änderungen, die wir bisher gesehen haben (von Alpha zu Beta,
und RC). Es ist verständlich in diesen Phasen und da es religiös steckt
zu der Philosophie, mit der es mich aus meinen minimalistischen Backbonejs herausbekehrte.
Die ganze Idee dieses ngModules hat sich für mich als etwas widersprüchlich erwiesen
produktiv. Und es ist traurig zu sehen, wie viel Zeit ich in die Evangelisation stecke
Reiche Güte geht an die minimalistischen und aufblähfreien „Components“.
absolut Verschwendung.
Am 29. August 2016 um 9:44 Uhr schrieb "Daniel Schuba" [email protected] :

Lesen, was @aluanhaddad https://github.com/aluanhaddad entnommen hat
die dokumente von eckig Ich habe das Gefühl, ich muss alles überdenken, was ich habe
etwas über Angular 2 gelernt und vielleicht sogar, wenn es dafür kein Framework gibt
behandelt Abhängigkeiten besser.

So wie ich es verstehe. Wenn ich ein App-Modul habe, das HttpModule importiert und ich
ein Feature-Modul mit einem Dienst haben, der den Http-Dienst verwendet, sollte ich nicht
Importieren Sie HttpModule auf Feature-Modul-Ebene, aber auf App-Modul-Ebene. Na und
wenn ich ein Funktionsmodul erstelle, das von vielen App-Modulen gemeinsam genutzt wird? ich habe
wirklich auf HttpModule, das im App-Modul importiert wird. Ich kann nicht sagen,
dass mein Feature-Modul vom HttpModule abhängt. Das ist wirklich hässlich und
bedeutet, dass der NgModule-Definition viele Funktionen fehlen, wie zum Beispiel
Peer-Abhängigkeiten.
Oh Junge. Es fühlt sich an, als würde Angle 2 auseinander brechen. Ich fürchte, es ist an der Zeit
Beginnen Sie von vorne, verwerfen Sie Winkel 2 und beginnen Sie mit Winkel 3.


Sie erhalten dies, weil Sie diesen Thread abonniert haben.
Antworten Sie direkt auf diese E-Mail und zeigen Sie sie auf GitHub an
https://github.com/angular/angular/issues/10552#issuecomment -243066961,
oder den Thread stumm schalten
https://github.com/notifications/unsubscribe-auth/AF675h8_np9i5cHgL8mMOOu8vMMQmWKkks5qkpv8gaJpZM4Jee-o
.

Könnte mich jemand korrigieren, wenn ich falsch liege.

Ich denke darüber nach, eine App wie folgt zu organisieren.

App
|--Recht/
|----VieleKomponenten.
|----LawNGModule.
|--Benutzer/
|----VieleKomponenten
|----UserNGModule
|--AppNGModule
|--SomeFirstLeveComponents

Nehmen wir an, ich möchte mit Angular Material arbeiten. Vorher habe ich es irgendwie gehasst, dass ich zu viel Boiler Plate hatte, um jedes Element in jede Komponente zu importieren. Jetzt würde ich es dem NG-Modul hinzufügen. Aber da ich mich entschieden habe, ein ng-Modul pro Funktion zu verwenden, muss ich die Importe für jedes ng-Modul durchführen, das ich in Betracht ziehe. Nicht nur die Wurzel. Ist das richtig?

Oder ist dies vielleicht ein Fall, in dem Sie ein Modul x erstellen, um y(Material) ein anderes Modul erneut zu exportieren, und Sie importieren es in die Module, die Sie benötigen?

@ReneVallecillo Du hast Recht. Sie müssen es in jedem Funktionsmodul importieren. Oder Sie fügen es zusammen mit anderen Modulen zu einem gemeinsam genutzten Modul hinzu (wobei die Abhängigkeit ausgeblendet wird), das es erneut exportiert und dann dieses gemeinsam genutzte Modul verwendet. Und wenn Sie es in ein anderes Modul erneut exportieren, haben Sie möglicherweise sogar doppelte Importe, ohne es sofort zu wissen und zu sehen.

@robwormald Als Antwort auf Ihren obigen Kommentar :

Im AoT-Modus funktioniert dies jedoch etwas anders – zur Build-Zeit extrahieren wir statisch (d. h. ohne Ausführung Ihres Codes) dieselben Metadaten aus dem Quellcode, indem wir nach Decorators suchen.

Bedeutet dies, dass Sie Module statisch aus dem ursprünglichen Quellcode extrahieren und wir daher Module effektiv nicht dynamisch erstellen können?

Um die Migration zu vereinfachen, dachte ich darüber nach, eine Funktion zu erstellen, die Module dynamisch erstellt; etwas wie das:

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

Während dies (wahrscheinlich?) Mit der JIT-Kompilierung funktionieren würde, würde es mit AoT nicht funktionieren, da AoT den Quellcode statisch analysiert und nach Dekorateuren sucht?

Diese unnötige Komplexität in einer Ära von ES@next.... @aluanhaddad macht einige sehr gute Punkte.

So wie die Dinge stehen, kann ich mir unmöglich vorstellen, dass mein Team oder ich mit Angular 2 vorankommen, wenn dies die beabsichtigte Richtung ist. Und es scheint so zu sein, da dies "geschlossen" wurde.

Ich muss es vielleicht wie @DaSchTour machen und andere Frontend-Frameworks recherchieren. Schade, denn vor ein paar Monaten war NG2 eine Freude, mit der ich arbeiten konnte, und meine offensichtliche Wahl aus dem Wurf.

@iyobo Abgesehen von den anfänglichen Schmerzen bei der Umstellung war die _große Mehrheit (und ich spreche mit _vielen_ Entwicklern) des Feedbacks zu NgModules positiv.

Isoliert in einer Hallo-Welt-App betrachtet, könnte man argumentieren, dass es „komplex“ ist („unnötig“ ist sachlich falsch, gemäß der obigen Erklärung), aber in einer echten Anwendung kommen sie wirklich zur Geltung – Organisieren von Funktionen, faules Routing und AoT werden mit NgModules so viel einfacher gemacht. Wenn ich heute die Wahl hätte, würde ich mich immer noch dafür entscheiden, NgModules in das Framework aufzunehmen.

Ich bin hier bei @robwormald , der anfängliche Schmerz der Migration von RC4/5 zu NgModules war überschaubar, nachdem ich die Vorteile gesehen hatte, nicht jede einzelne Komponente/Pipe in eine neu erstellte Seite importieren zu müssen.
NgModule beginnen zu glänzen, nachdem sie etwas komplexer geworden sind und viele gemeinsame Komponenten haben.

So viel einfacher, SharedModule einfach zu importieren und fertig zu sein.

Hey @robwormald , Die Vorstellung, dass man mit der aktuellen Richtung von Ng2 nicht einverstanden ist, ist in keiner Weise eine sachliche Behauptung, dass sie nur an Apps auf „Hallo Welt“ -Ebene arbeiten.

Diese "Unterteilung von Funktionen", von der Sie sprechen, ist nichts Neues. Es ist etwas, das immer nach Bedarf für jedes einzelne Produkt / jede einzelne Lösung mithilfe von Komponenten entwickelt wurde.
Allerdings gibt es immer noch keine größere Abschottung als eine Komponente, die von sich aus erklärt, was sie benötigt.

Was Lazy Loading, Zurückziehen und Betrachten der Dinge aus der Vogelperspektive betrifft, so besteht der größte Segen des Lazy Loading darin, die Ladegeschwindigkeit der App zu verbessern. Ich denke, die meisten von uns haben Pipelines, mit denen dies funktioniert. Geben Sie Minifizierung, Komprimierung und mehrere App-Einstiegspunkte ala Webpack ein.

Es scheint mir nur, dass NgModules eine Lösung auf der Suche nach einem Problem ist, als eine Lösung für ein tatsächliches Problem. Aber ich kann auch nicht behaupten alles zu wissen...

Ich denke, die Zeit wird zeigen, ob die Einführung von NgModules eine gute Idee war. Ich habe den Eindruck, dass Angular 2 derzeit nur dafür gemacht ist, bestimmte Designziele zu erreichen. Niemand hat sich Gedanken über Dinge wie Teams mit unterschiedlichen Fähigkeiten, Code, der älter wird und über Generationen von Entwicklern weitergegeben wird, gemacht. In einer idealen Welt mag es wie eine großartige Idee aussehen. Aber in Wirklichkeit führt NgModules viele Fallen und Verschleierungen ein, die in der Phase des Trainings und der Einführung in ein neues Projekt viel Ärger verursachen werden. Es ist einfach nicht so einfach und intuitiv wie bei der Deklaration auf Komponentenebene. Abhängigkeiten sind in Modulen versteckt und es ist nur eine Frage der Zeit, bis Sie nach dem Modul suchen müssen, in dem sich Ihre Komponente befindet.

Nachdem ich kürzlich eine größere Anwendung auf NgModule umgestellt habe, denke ich, dass sie größtenteils eine gute Sache sind (jetzt, wo ich damit fertig bin, macht es einen gewissen Sinn). Ich denke tatsächlich, dass das Hauptproblem darin besteht, dass sie eine andere Komponentenstruktur erfordern, was wahrscheinlich nicht gut zu Ihrer vorherigen Strukturierung Ihrer Anwendung passte (zumindest war das bei mir der Fall).

Ich bin jedoch der Meinung, dass sie nicht als einzige Lösung existieren sollten. Wenn Sie sich ansehen, wie Komponenten sehr häufig aufgebaut sind, stellen Sie fest, dass sie sehr oft aus kleineren, hochspezialisierten Teilkomponenten bestehen. Für diese Unterkomponenten, die außerhalb dieser Containerkomponente keinen Zweck haben, ist es wirklich mühsam, sie im Modul mit höherem Geltungsbereich zu verwalten, und kann schnell zu Umfangsproblemen führen.

Ich würde es wirklich begrüßen, wenn es _zusätzlich_ zu NgModules einen Mechanismus gäbe, der es Komponenten erlaubt, andere Komponenten oder Direktiven als lokal begrenzte Abhängigkeiten zu definieren, die nur innerhalb dieser genauen Komponente gelten (so wie die directives -Auflistung vor Modulen funktionierte).

Ich mag den Vorschlag von @poke , eine Alternative für diejenigen zu haben, die lieber nicht auf Full NgModules gehen möchten.

NgModule wurden in RC5 hinzugefügt, um Probleme beim Kompilieren und verzögerten Laden zum Laufen zu bringen - also kaum Teil des ursprünglichen Masterplans, weshalb sie für einige Anwendungsfälle nicht gut geeignet sind (insbesondere wenn Sie eine App basierend auf das ursprüngliche "Komponenten sind König"-Design).

Natürlich beheben oder ermöglichen sie einige Dinge, bringen aber auch ihre eigenen Komplikationen mit sich – mehr Dinge, die die Leute lernen und um die herum sie entwerfen müssen, was besonders herausfordernd ist, wenn noch nicht alle Best Practices und Ansätze ausgearbeitet wurden. Eine frühe Adoption kann viel Schmerz bringen, das habe ich von der Fahrt zu RC4 gelernt.

Ich mochte den ursprünglichen komponentenzentrierten Plan mehr, weshalb ich Polymer / Web Components jetzt wahrscheinlich besser finde. Module fühlt sich einfach wie ein halber Schritt zurück zu Angular 1 an.

Anfangs war ich gegen diese Änderung des Entfernens von Pipes und Direktiven resistent, aber jetzt gewöhne ich mich daran und es scheint nicht so schlimm zu sein, wie ich zuerst dachte.

Kann mir jemand zeigen, wie NgModules in einer wirklich komplexen App funktioniert, in der mehrere Komponenten mehrere andere auf mehreren Ebenen erfordern? Alle Tutorials, Beispiele und Repos, die ich gesehen habe, zeigen nur die einfachen Möglichkeiten, wie ein Modul seine eigenen Inhalte kapselt und einige davon für andere veröffentlicht (exportiert).

In realen Projekten gibt es viele übergreifende Abhängigkeiten, die normalerweise hierarchisch verkettet sind. Es ist irgendwie falsch, einen Begriff von etwas durch ein genau dafür bestimmtes Beispiel zu beweisen.

@für alle Autoren von Angular2: Können Sie uns bitte ehrlich sagen, was die negativen Teile von NgModules sind? Ich weiß, dass man über alle guten Dinge ein Buch schreiben kann. Das ist gut. Aber ich muss mich immer mit den versteckten schlechten Dingen auseinandersetzen, die nicht klar würden, wenn du nicht darüber sprichst.

Kann mir jemand zeigen, wie NgModules in einer wirklich komplexen App funktioniert, in der mehrere Komponenten mehrere andere auf mehreren Ebenen erfordern?

Eine Möglichkeit wäre, ein Abhängigkeitsmodul nur für diese Komponenten zu erstellen: Nehmen wir an, Sie haben drei Gruppen von Komponenten A , B und C , die mehrere Komponenten enthalten jeder Satz hat diejenigen, die etwas verwandt sind. Diese drei Sätze würden also gut für drei separate Module funktionieren.

Jetzt erfordern Komponenten in jedem dieser Sets mehrere Komponenten aus einem Set D . Diese Komponenten in D werden nur für die Komponenten in diesen drei Sätzen verwendet. Da sie in allen verwendet werden, können Sie die Komponenten nicht einfach zu diesen Modulen hinzufügen (da Komponenten möglicherweise nur Teil eines einzelnen Moduls sind). An dieser Stelle könnten Sie A , B , C und D zu einem gigantischen Modul zusammenführen, sodass alle Abhängigkeiten vorhanden sind. Aber das ist natürlich sehr fummelig. Stattdessen erstellen Sie einfach ein neues Modul für D , das nur diese Abhängigkeiten enthält. Dieses Modul tut nichts anderes, als den Zugriff auf diese Module bereitzustellen. Jetzt können Sie dieses Modul in jedes dieser drei anderen Module importieren und die Komponenten verwenden. Da die Komponenten aber immer noch „privat“ sind, exportieren Sie das Modul nicht erneut oder importieren das Modul D in ein anderes Modul.

Da Modulimporte nur das Modul selbst betreffen, ermöglicht dies eine Art Scoping, ohne andere Module zu verschmutzen. Natürlich müssen Sie mehr Module erstellen, aber so funktioniert es.

Ich kann mein aktuelles Setup teilen. Ich habe 3 Module in der App verwendet: CommonModule, AppModule und TestModule.

  • CommonModule importiert und exportiert die gängigsten Inhalte wie HttpModule, FormsModule, MdInputModule usw
  • AppModule importiert BrowserModule, CommonModule, app.routing und einzelne Komponenten
  • TestModule importiert und exportiert BaseModule, überschreibt aber einige Anbieter, wie XHRBackend mit MockBackend

Ich habe dieses Setup eingeführt, um TestBed.configureTestingModule zu vereinfachen,
so dass ich TestModule importieren muss und dann nur eine einzelne Komponente wie:

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

Ein weiterer Nachteil, der mir beim Wechsel von RC-4 zur Veröffentlichung deutlich wurde, war, dass NgModule eine schwere Strafe für einfache Refactorings mit sich bringen, bei denen eine Komponente einfach aufgeteilt werden muss. Bei NgModules müssen Sie das enthaltende Modul ändern, das sich möglicherweise mehrere Ebenen höher im konzeptionellen Komponentenbaum befindet, oder die Komponente heraufstufen, indem Sie sie in ein NgModule einschließen und sie dann aus ihrem übergeordneten NgModule entfernen. Das Refactoring von Komponenten ist unerlässlich.

Dies hängt direkt mit dem Punkt von @poke zusammen

Ich würde es sehr begrüßen, wenn es zusätzlich zu NgModules einen Mechanismus gäbe, der es Komponenten ermöglicht, andere Komponenten oder Direktiven als lokal begrenzte Abhängigkeiten zu definieren, die nur innerhalb dieser genauen Komponente gelten (genauso wie die Auflistung der Direktiven vor den Modulen funktionierte).

Ich widerspreche stark. Eine modulare Architektur, wie sie von Angular 2 vorgeschlagen wird, lässt sich einfacher skalieren, anpassen und bei Bedarf umgestalten. Sicher, von RC4 zu RC5 gab es ein bisschen Anpassung, aber wenn überhaupt, haben sich NgModule für mich als viel flexibler erwiesen.

Angular ist rechthaberisch und sicherlich keine Einheitsgröße, aber NgModules ist genauso sicher nicht der Fehlerpunkt bei der Entwicklung einer intelligenten, modernen und hochleistungsfähigen Anwendung.

@emilio-martinez: Meiner Meinung nach würde NgModule niemals eingeführt werden, wenn Angular 2 nicht so langsam beim Bootstrapping wäre, wenn es um JiT geht. Alle anderen „Verbesserungen“ wie „Skalieren, Anpassen und Refactoring“ sind strittig, wie diese Diskussion zeigt.

Es ist jetzt schon eine ganze Weile her und viele von uns hatten Zeit, NgModule vollständig in unsere Arbeit aufzunehmen. Ich denke, es ist jetzt klar, dass, wie einige Leute beschrieben haben, es einige ziemlich großartige Dinge ermöglicht, sobald Sie die Bremsschwelle des Wechsels zum neuen Modulsystem hinter sich gelassen haben. Für alle, die diesen Thread nutzen und Probleme haben, NgModule zu absorbieren, empfehle ich, ganz durchzuscrollen und alles von @robwormald und @wardbell zu lesen, insbesondere.

Ich glaube, wir alle werden in einem Jahr feststellen, dass viele Angular 2+-Anwendungen Module, Lazy Loading und AOT umfassend und nahtlos nutzen. Ich glaube, dass es für die meisten oder fast alle Anwendungen völlig routinemäßig sein wird, diese Dinge zu verwenden, um die Vision einer "progressiven Anwendung" zu implementieren, bei der selbst große komplexe Anwendungen eine nahezu sofortige anfängliche Ladezeit haben und dann die Funktionalität sie träge laden (oder optimistisch träge vorladen). müssen. Das Ergebnis ist tatsächlich erstaunlich glatt und wird für den einzelnen Anwendungsentwickler zu bemerkenswert niedrigen Kosten erzielt: NgModule ist im Grunde dieser Preis, und es ist ein irritierender Übergang, aber dann nur ein sehr bescheidener Arbeitsaufwand.

@kylecordes Ich hoffe, du hast Recht und ich denke, das ist die richtige Einstellung.

@iurii-kyrylenko das ist sehr wahr.

Ich habe ein Problem mit der eckigen Kompilierung meines JavaScripts, da es mit TypeScript kompiliert werden soll, aber das ist ein separates Problem.

@kylecordes Ich denke, es gibt viel mehr zu beachten als nur den Übergang. Module bringen viel Komplexität und viele zusätzliche Möglichkeiten, Fehler in die eigene Anwendung einzufügen. Das größte Problem ist die Verschleierung von Abhängigkeiten. Was in den nächsten Jahren der Entwicklung mit Angular 2 für viel Ärger sorgen wird.

@aluanhaddad Ich glaube, Angular verwendet zum Kompilieren einen TSC-Wrapper. Es ist schön, weil Sie es beispielsweise sogar in einen Task-Runner-Workflow implementieren können.

Die Bootstrapping-Geschwindigkeit von @iurii-kyrylenko ist basierend auf RC4 ebenfalls schwer zu bestimmen. Ein Großteil der Arbeit, die von damals bis zur endgültigen Veröffentlichung geleistet wurde, bestand in der Bereinigung und Optimierung. Meiner Erfahrung nach läuft Angular kompiliertes JIT ohnehin schneller als RC4.

@DaSchTour kannst du näher auf die Fehler eingehen, die du bei der Arbeit mit NgModule gefunden hast?

@emilio-martinez Es sind keine Fehler in NgModule, sondern Fehler, die aufgrund fehlender Importe oder doppelter Dienstinstanzen auftreten, die weggelassen oder in einer früheren Entwicklungsphase gefunden worden wären. Es geht darum, Dinge dort zu importieren, wo ich sie verwende, und nicht irgendwo, wo ich nicht sehe, ob sie gebraucht oder verwendet werden und an welchem ​​Ort sie gebraucht und verwendet werden.

Denken Sie nur an TypeScript, das auf diese Weise funktioniert. Ich habe eine Basisdatei für mein Modul, nennen wir sie _index.ts_, sie sieht so aus.

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

StartComp.boot();

Dann haben wir eine Datei namens start.ts, die so aussieht.

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

Das macht Angular mit NgModules. Mit etwas Magie habe ich etwas in ein Modul importiert und es erscheint am anderen Ende meiner Anwendung. Sie müssen wissen, dass foo in index.ts importiert wird und durch Ausführen von StartComp aus index die dortigen Importe in der Komponente verwendet werden können.

Die Abhängigkeiten sind ausgeblendet und erfordern zusätzliche Untersuchungen, um sie zu finden.

@emilio-martinez

Meiner Erfahrung nach läuft Angular kompiliertes JIT ohnehin schneller als RC4.

Ich habe ein Projekt mittlerer Komplexität, basierend auf MEAN Stack und Angular 2 Final. Es dauert ungefähr 10 Sekunden , um den Bootstrap im JIT-Modus auf meinem Android-Gerät abzuschließen. Ich halte dies für eine erhebliche Verzögerung. Derzeit kann ich die AOT-Kompilierung nicht verwenden, ohne meinen Quellcode zu ändern (Probleme mit privaten Mitgliedern, Elvis-Operator ...).

Hat jemand Informationen zur Leistung von AOT + Lazy Load für reale Projekte?

Ich glaube, Angular verwendet zum Kompilieren einen TSC-Wrapper. Es ist schön, weil Sie es beispielsweise sogar in einen Task-Runner-Workflow implementieren können.

@emilio-martinez genau das will ich nicht. Ich möchte meinen Code mit einer beliebigen Version von TypeScript kompilieren, z. B. 2.1.0-dev, die eine niedrigere Ausgabe für async/await hat. Ich möchte nicht, dass Angular für das Kompilieren meiner TypeScript-Dateien verantwortlich ist, dies sollte nicht an ein Framework delegiert werden, es ist die Rolle einer Sprache. Ohne weiter vom Thema abzukommen, hätte ich @Script nicht mit einer zehn Fuß langen Stange berührt, Gott sei Dank ist es tot.
In Bezug auf den Workflow verwende ich JSPM und manchmal Webpack, keinen traditionellen Task-Runner, und ich lasse meine IDE meine Linters verarbeiten.

Ein weiteres Problem ist, dass ich Dekorateure geschrieben habe, die über eckige Dekorateure abstrahieren, und ich verstehe jetzt, dass aot sie ignorieren wird. In Anbetracht dessen, wie stark Winkel von Dekoratoren sind, war ich sehr enttäuscht zu erfahren, dass das Framework Dekoratoren nicht vollständig unterstützt und sie während AOT als statische Anmerkungen behandelt, obwohl sie tatsächlich ein Laufzeitkonstrukt in der zugrunde liegenden Sprache sind.

@aluanhaddad Es ist wichtig zu verstehen, dass während der AoT-Kompilierung zwei unterschiedliche Schritte ausgeführt werden - der erste ist das Generieren von _neuem_ Typoskript-Code, der zweite das Transpilieren dieses Codes auf ES5/6. ngc macht beides aus Bequemlichkeit, aber es gibt nichts in AoT, das dies erfordert. Innerhalb von Google tun wir beides, und daher hat dieser Fall Priorität. Jeder konnte einen Compiler-Host implementieren, um die Codegenerierung in jeder gewünschten Umgebung zu unterstützen.

Wir unterstützen (noch) keine Abstraktion zusätzlich zu den eingebauten Decorators von angle, aber wenn Sie so etwas wie https://www.npmjs.com/package/core-decorators verwenden möchten, wäre das in Ordnung.

@iurii-kyrylenko schlägt vor, dass Sie sich die Keynote von Tag eins von AngularConnect ansehen, wo LucidCharts über ihre Erfahrungen mit AoT sprach. Siehe https://youtu.be/xQdV7q3e_2w?t=1411

IMHO - das oberste Ziel aller sollte es sein, so schnell wie möglich auf die AoT-Compilation zu kommen. Die Leistung ist einfach unschlagbar.

@robwormald Ich habe mir nicht angesehen, welche Optionen beim Anrufen ngc verfügbar sind - daher ist dies möglicherweise bereits abgedeckt. Ich denke, dass diese Optionen die Bedenken wie die hier geäußerten zerstreuen könnten, wenn sie deutlich machen, dass NGC den ersten Zweck als Hauptgrund erfüllt, um im zweiten Zweck als Bequemlichkeit/Optimierung zu existieren. Wenn die Dokumentation oder Hilfe zeigt, wie man separat erhältliche tsc für diejenigen ausführen kann, die dies vorziehen, könnte dies die Bedenken weiter zerstreuen?

@kylecordes Ich glaube nicht, dass die Dokumentation in absehbarer Zeit behandeln wird, wie Sie Ihren eigenen Compiler-Host implementieren können. Es ist ein fortgeschrittener Anwendungsfall und würde daher einiges an selbstgesteuertem Lernen erfordern, um es zu implementieren. Wir haben hier https://github.com/angular/angular-cli/tree/master/packages/webpack etwas Ähnliches für die CLI implementiert

@robwormald Ah, ich meine nicht, dass Sie Ihren eigenen Compiler-Host implementieren. Ich meinte nur einen zweizeiligen "Erstellungsprozess" - zuerst Aufruf ngc , um ein generiertes Typoskript auszugeben, dann Aufruf tsc selbst, um das gesamte Typoskript (Ihre Quelle plus die generierte Quelle) zu kompilieren JavaScript. Dies bietet eine schnelle Gewissheit, dass der Typoskript-Code lediglich vom handelsüblichen Typoskript-Compiler in JS kompiliert wird.

@robwormald Danke für deine Antwort.
In Bezug auf NGC möchte ich wissen, ob ich die TypeScript-Compiler-Version und -Einstellungen im TS -> TS -Pass steuern kann. Kann ich TypeScript an NGC übergeben oder muss ich eine bestimmte Version verwenden, die eine bestimmte TypeScript-Version umschließt? Wie gekoppelt sind sie?

Gibt es in Bezug auf Decorators eine Problemverfolgungsunterstützung für benutzerdefinierte Decorators, die über Angular-Decorators abstrahieren? https://www.npmjs.com/package/core-decorators ist ein orthogonaler Satz von Decorators, aber ich habe Decorators, die Muster und Konventionen in meinen Angular-Apps erzwingen, indem sie Angular-Decorators umschließen. Ein offensichtlicher Anwendungsfall dafür ist das automatische Erstellen und Erzwingen von paketweiten Präfixen für Komponentennamen, aber es gibt auch andere.

Da NGC dies nicht unterstützt, woher weiß es, welche Dekorateure Angular-spezifisch sind?
Passt es namentlich zu eckigen Dekorateuren?
Ich hoffe nicht, denn das würde den lexikalischen Geltungsbereich von JavaScript verletzen.
Ein einfaches Szenario
_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);

_consumer.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 Haben Sie eine Lösung gefunden, um Komponenten dynamisch zu laden, ohne Komponentendeklarationen zum Root-Anwendungsmodul hinzuzufügen? .

Ich bin auch Teil eines Migrationsprojekts von Angular 1.X zu Angular 4. Dieses Projekt verfügt über eine große Anzahl von Komponenten, die in verschiedenen Anwendungen wiederverwendet werden, die je nach Anwendungskontext verzögert geladen werden.

Nach meinem Verständnis in Angular 4

Wir müssen Komponentenabhängigkeiten wie unten in Root- @NgModule- Deklarationen hinzufügen.

importiere {platformBrowserDynamic} aus "@angular/platform-browser-dynamic";
importiere {Komponente, NgModule} aus „@angular/core“;
...
...
@NgModule({
imports: [BrowserModule ], // BrowserModule von Angular importieren
Bootstrap: [BootStrapComp], // Geben Sie die Bootstrap-Komponente an
Deklarationen: [com1, comp2 , comp5 ...... Comp n ] // registriere unsere Komponente mit dem Modul
})
Exportklasse AppModule {}

PlattformBrowserDynamic().bootstrapModule(AppModule);

Aber in unserem Fall wollten wir NgModule nicht rooten, um über Komponentenabhängigkeiten in der Kompilierzeit Bescheid zu wissen. Vielmehr wollten wir, dass Komponenten zur Laufzeit dynamisch geladen werden.
Haben Sie gute Lösungen gefunden, die Anwendungen booten können, ohne alle Komponenten in Root-NgModule-Deklarationen hinzuzufügen (Und wir wollten auch nicht ein NgModule für jede Komponente haben :))

@DaSchTour

Erinnerst du dich an die Zeiten, in denen dein App-Einstiegspunkt so aussah?

Nun, einige von uns haben ein Build-Skript verwendet, um diese Module automatisch anzufordern und sie dem App-Modul hinzuzufügen.

Ich suche nach einer ähnlichen und einfachen Lösung in angle2.

@samudrak Sie können nicht nur die Komponente faul laden, wenn Sie die Unterstützung von Angular aot verwenden möchten. Sie müssen das Lazy-Modul für jede Komponente einrichten und das Modul faul laden. Wir verwenden einen ähnlichen Ansatz in unserer Anwendung ...

Mit Unterstützung für dynamische Importe in ECMAScript und jetzt in TypeScript (mit vollständiger Typprüfung orthogonal zum Laden) ist der Anwendungsfall für verzögertes Laden ziemlich willkürlich. Natürlich ist im Nachhinein 20/20 und es gab keine Möglichkeit zu wissen, dass das passieren würde.

Dieses Problem wurde aufgrund von Inaktivität automatisch gesperrt.
Bitte reichen Sie ein neues Problem ein, wenn Sie auf ein ähnliches oder verwandtes Problem stoßen.

Lesen Sie mehr über unsere Richtlinie zum automatischen Sperren von Gesprächen .

_Diese Aktion wurde automatisch von einem Bot ausgeführt._

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen