Webpack 2 Parameterübergabe and den Buildprozess auf der Konsole


Die meisten Beispiele für Webpack enthalten fertige Konfigurationen die als npm scripte hinterlegt sind. Wenn man aber einen automatisierten Build Prozess verwendet z.B. über den TFS, dann möchte man evtl. einige Variablen von außen an den Buildprozess übergeben. Dazu könnte z.B. die “baseUrl” gehören, wenn die Anwendung nicht im Root des Webserver gehostet wird.

Wenn man z.B. angular-starter installiert und man an den Befehle für “build:prod” noch den Namen der Anwendung übergeben möchte, damit dieser als “baseUrl” gesetzt wird, dann sind dafür die folgenden Schritte notwendig.

Anpassen der package.json, hier müssen zwei “- -“ (doppeldashes) entfernt werden, da sonst die Übergabeparameter nicht gesetzt/erkannt werden.

Vorher:

„build:prod“: „npm run clean:dist && npm run webpack — –config config/webpack.prod.js –progress –profile –bail“,

Nachher:

„build:prod“: „npm run clean:dist && npm run webpack –config config/webpack.prod.js –progress –profile –bail“,

Dann passen wir die “webpack.prod.js” an und prüfen ob der “appname” übergeben wurde und erweitern bei Bedarf die “environment” Variable um den Appnamen

Dann wird noch die “webpack.common.js” angepasst und wenn der “appname” gesetzt ist, ersetzen wir die “baseUrl”

jetzt können wir die passende Kommandozeile aufrufen und den passenden “appnamen” übergeben

npm run build:prod — –env.appname „meineAnwendung“

hier können wir jetzt beliebig viele Parameter übergeben z.B.

npm run build:prod — –env.appname „meineAnwendung“ –env.test “../testFolder”

Wenn wir den Befehl ausführen, dann kann man in der Konsole auch unser “console.log” sehen und man sieht das webpack hier ein JSON Objekt erstellt auf das wir entsprechend in der “webpack.prod.js” über die “env” Variable zugreifen können.  Damit lassen sich beliebige Informationen von außen über eine Buildumgebung noch an webpack übergeben.

CSS IntelliSense in Visual Studio mit Angular und Resharper


Manchmal könnte man sagen “früher” war alles besser. Zumindest war es mit Angular 1 und dem “alten” System in dem man noch direkt JavaScript und Styles eingebunden hat, einfacher im HTML die passende IntelliSense für die CSS Klassen mit der Hilfe von Resharper zu erhalten. Dabei handelte es sich z.B. um Bootstrap und font awesome Klassen.

Wenn man jetzt aber das ganze für Angular 2 möchte, wo alle Styles und Scripts nur noch aus dem node_modules Ordner referenziert werden und das Projekt mit Hilfe von Webpack gebaut wird. Gibt es nicht mehr “einfach” so die IntelliSense für die CSS Klassen.

Auch auf Addons wie Glyphfriend kann man leider nicht zurückgreifen, denn hier muss man die IntelliSense für HTML und CSS im Resharper ausstellen, damit die IntelliSense von Visual Studio greift. Dann hat man aber keine Autovervollständigung von Angular 2 Variablen im HTML Template mehr – was meiner Meinung nach noch wesentlich wichtiger ist.

Hier bleibt meines Wissens aktuell leider nur eine Möglichkeit, man kopiert sich die passenden css Dateien aus dem node_modules Ordner und fügt die Dateien bei sich im Projekt ein und macht noch einen Vermerk das die Dateien nur für die IntelliSense im Projekt enthalten sind aber nicht direkt referenziert werden.

image

wie man sieht hat man dann auch IntelliSense für Bootstrap 4 und die Klassen sind nicht alle unterstrichen (was normalerweise bedeutet das er die Klasse nicht kennt).

image

Auch font awesome geht wieder.

image

Out of Memory Exception beim EF Debuggen im IIS Express


Bisher noch nie vorgekommen, aber es gibt immer ein erstes mal. Heute hatte ich beim Abrufen großer Datenmengen um einen Cache zu befüllen auf einmal eine “Out of Memory” Exception, obwohl mein Visual Studio vom RAM her sehr gut aussah und auch noch genug RAM zur Verfügung stand.

Leider gibt die Fehlermeldung auch nicht mehr her, weder Stacktrace, noch eine Innerexception. Daher erst einmal Google befragt und hier findest sich auch nicht wirklich etwas brauchbares, außer das man wahrscheinlich in einer x86 Anwendung arbeitet oder seinen Code in x86 kompiliert hat. Das war bei mir aber nicht der Fall, ich habe alles mit “AnyCpu” kompiliert.

Leider weiß ich nicht mehr wie ich auf die Idee kam, das es ja auch am IIS Express liegen könnte, denn auf dem Server wo die Anwendung bereits ausgerollt war funktionierte es ja bestens. Und siehe da standardmäßig nimmt VS den IIS Express mit 32Bit und wieder habe ich ein Optionsmenü in VS gesehen was ich bisher noch nicht kannte, in dem man einstellen konnte das VS den IIS Express standardmäßig mit 64Bit startet.

Extras => Optionen => Projekte und Projektmappen => Webprojekte

image

und “schon” war meine “Out of Memory” Exception beim Abrufen von EF Daten in meiner Webanwendung gelöst.

ngModel like two-way-databinding für Komponenten in Angular


Da es sich bei Angular nur noch im Komponenten handelt, ist es hier natürlich auch wichtig wie man Daten an Komponenten weitergibt und auch wieder zurückgeben kann. Dafür gibt es zwei wichtige Dekoratoren “@Input” um Daten an eine Komponenten zu übergeben und “@Output“ um Daten wieder “zurückzugeben”.

Um ein two-way-databinding zu erstellen gibt es mindestens zwei Möglichkeiten.

V1 eine ngModel Like Datenbinding mit “banana in the box” Syntax  [(name)] hier muss in der Childkomponente bei der Namensgebung des Output Dekorators darauf geachtet werden, das dieser am Ende des Namens “Change” stehen hat und der Name selbst dem vom Input Dekorator entspricht.

V2 hier handelt es sich um die “normale” Bindung mit zwei Attributen eine für die Eingabe der Werte mit eckigen Klammern  “[age]” und dann noch um eine Eventbindung mit  runden Klammern “(ageChanged)” um die Daten die aus der Child Komponente zurückgegeben werden auszuwerten. Auch hier werden wieder zwei Dekoratoren benötigt der Input um die Daten an die Komponente zu senden und der Output Dekorator um das Changed Event aufzurufen.

Parent Komponente

Child Komponente

Wie man in beiden Fällen sieht wird in der Child Komponente für den Output Dekorator ein EventEmitter erstellt mit einem bestimmten Typen (bei uns string), der als Rückgabewert im emit für den EventEmitter übergeben werden muss. Bei dem Wert den man an emit übergibt, handelt es sich um den Rückgabewert und dieser muss immer entsprechend “manuell” angestoßen werden, bei uns z.B. über das “keyup” Event unseres Inputs.

Dazu gibt es noch ein funktionierendes Plunkr Beispiel.

Visual Studio 2013/2015 bereitgestellte nodejs Version veraltet


Wenn man Visual Studio installiert wird bereits eine nodejs Version mit installiert, aber nicht im Standardpfad von nodejs. Wenn man also eine aktuelle nodejs Version auf seinem System installiert hat, verwendet diese Visual Studio NICHT automatisch. Meist merkt man dies erst, wenn man versucht npm pakete über Visual Studio zu installieren und in der Ausgabe Fehler erscheinen

npm WARN package.json @ No description
npm WARN package.json @ No repository field.
npm WARN package.json @ No README data

npm ERR! node -v v0.10.31
npm ERR! npm -v 1.4.9
npm ERR! code E404

===npm command completed with exit code 1====

und es werden keine npm Pakete installiert.

Daher ist es notwendig das man nodejs auf dem Rechner selbst installiert und dann in Visual Studio als externes Webtool Einträgt. Sobald man nodejs installiert hat, geht man in Visual Studio auf

“Extras => Optionen => Projekte und Projektmappen => Externe Webtools”

und fügt dort den aktuellen Installationspfad von nodejs hinzu und verschiebt diesen ganz nach oben. Dann muss Visual Studio noch einmal neu gestartet werden und jetzt klappt es auch mit der Installation der npm Pakete.

nodeJsVisualStudioEinstellen

Wenn ein update von npm notwendig ist, dann einfach über die normale Konsole global aktualisieren und in Visual Studio wird dann ebenfalls diese Version verwendet.

npm cheat sheet


Da ich selbst node und  npm noch nicht so lange verwende, muss ich hin und wieder einige für mich wichtige Befehle nachschauen. Daher nachfolgend einige npm Befehle. Da ich die Befehle nur unter Windows verwende, kann ich leider nicht sagen ob es da signifikante Unterschiede zur Linux Version gibt,

Wenn man dann noch hinter einem Proxy sitzt, dann sind die folgenden npm Befehle ebenfalls sehr hilfreich, denn man kann den Proxy explizit für npm angeben.

Http “Interception” in Angular 2


Wenn man in Angular 1 Requests und Responses verändern will, ist dies sehr einfach mit der Hilfe von Interceptoren lösbar. Ich habe hier einige benutzerdefinierte Interceptoren erstellt die einem das Leben schon sehr einfach machen konnten. Wenn es darum ging den IE vom Caching der Ajax Requests abzuhalten oder um zu zählen wie viele offene Requests aktuell noch vorhanden sind um einen kleinen Spinner anzuzeigen, das gerade noch etwas geladen wird, …

Leider ist dies in Angular 2 nicht mehr so einfach möglich, oder sagen wir mal so es ist etwas umständlicher möglich, denn leider bietet Angular 2 aktuell keinen so komfortablen weg, wie ihn Angular 1 geboten hat.

In Angular 2 müssen wir dafür die Http Klasse “erweitern”. Damit wir die Benutzerdefinierte Implementierung unserer Http Klasse auch in anderen Projekten verwenden können ohne diese jedes mal selbst anzupassen, verwende ich noch rxjs Subjects, damit kann man die spezielle Implementierung unserer Lösungen an anderer Stelle aufrufen (Subscriben). Die Implementierung kann hier z.B. folgendermaßen aussehen:

In der CustomHttp Klasse findet keine direkte Implementierung statt, sondern es wird ein Service Injected der selbst rxjs Subjects für “jedes” Problem bereitstellt, was ich in meinen Webseiten kenne und für das ich teilweise andere Lösungen bereitstelle, wie z.B. was mache ich wenn ein Serverfehler auftritt. Ich habe hier aktuell nur die “No-Cache” Header fest eingebunden, da ich diese immer benötige. Sonst ruft man hier nur die passenden Service Funktionen auf und diese triggern dann das rxjs Subject, welches an anderer Stelle abonniert werden kann.

Der “httpSubjectService” kann dann z.B. in der “app.component” (Root Komponente) eingebunden werden und man subscribed das jeweils passende Subject und kann die passende Implementierungen dann entsprechend aufrufen.

Damit aber die CustomHttp Erweiterung überhaupt geladen werden kann muss die benutzerdefinierte Implementierung registriert werden im Dependency Injector (sehr gute Hilfe die erklärt wie die Dependency Injection in Angular 2 funktioniert) von Angular 2 und man überschreibt damit die Standardimplementierung von Http mit der CustomHttp Implementierung.

Natürlich darf man nicht vergessen das “CustomHttpCoreModule” im “app.module” zu registrieren.

Ein komplettes Beispiel auf meinem Github Account.