Starten mit React

Einleitung

Da ich nun auch mal wieder in die Web-Entwicklung mit einsteigen wollte, habe ich mir erst mal angeschaut, welche Wege es nun gibt. Dabei ist mir Angular JS und React vor die Füße gelaufen. Nach längerem ausprobieren, hab ich mich nun für React entschieden, da mir dort die Vorgehensweise einfach besser gefällt.

Vorbereitung

Um ein Unterstützung durch Highlighting und IntelitiySense zu bekommen, hab ich mir zuerst Visual Studio Code installiert und zusätzlich noch NodeJS, mit welchen React am angenehmsten zu Entwickeln ist. Bei NodeJS benutze ich die aktuelle und nicht die LTS Version. Und damit das erzeugen der Projekte einfacher von der Hand geht, hab ich gleich das Packet „create-react-app“ installiert:

npm install -g create-react-app

Projekt erstellen

Mit create-react-app wird die Projektmappe erstellt und es kann direkt die erste Oberfläche betrachtet werden:

create-react-app example-app
cd example-app
npm start

Nach kurzem kompilieren wird der Webbrowser geöffnet und direkt auf die Website navigiert. npm kann mit [Strg]+ unterbrochen werden, dies muss noch mit [j] bestätigt werden. Danach können wir nun weitere notwendige Packet installieren. Die Installation wird immer mit folgende Befehl, bei dem man im Hauptverzeichnis des Projektordners stehen muss, durchgeführt:

npm install --save <packet(e)>

Hierbei wird dem npm gesagt das er die angegebenen Packet installieren soll, sowie die Packete in der package.json zu hinterlegen sind. Dadurch kann man jederzeit den Zustand der Packete wieder herstellen.

Meine verwendeten Packete

PacketnameBeschreibung
bootstrap@4.0.0-betaBootstrap selbst für die CSS-Dateien
reactstrapImplementierung von Klassen für direkte Verwendung in React
react-addons-transition-groupWird von reactstrap als mit zu installieren definiert
react-addons-css-transition-groupWird von reactstrap als mit zu installieren definiert
react-router-domDarüber werden die Urls und ihre Darstellungen definiert, wenn mehr als eine Seite benötigt wird
react-loadableZum zerteilen der Javascript-Dateien, damit beim Start nicht mehr alles geladen wird
react-iconsVielerei an Icons fürs Web, hier noch ein Icon-Viewer zum ermitteln welche vorhanden sind

Proxy wegen CORS

Für die Datenbeschaffung wird hier häufig mit RESTfuly Anfragen gearbeitet. Diese sind nicht immer mit in der Website integriert, sondern werden oft von anderen Stelle her konsumiert. Dabei reicht schon ein anderer Port auf dem gleichen Computer und man landet in einem CORS-Fehler.

Damit diese Probleme für den einen REST-Dienst nicht auftritt, kann man im Webpack einen Proxy einrichten. Die Einstellungen werden in der package.json, die im Wurzelverzeichnis zu finden ist, auf der ersten Ebene direkt hinterlegt, z.B:

{
  "name": "example-app",
  "version": "0.1.0",
  ...
  "proxy": ...
}

Alle folgenden Angaben, beziehen sich auf den Eintrag „proxy“, der entsprechend belegt wird.

Single-Proxy

Der einfachste Weg ist es, alle Anfragen die von der React-Seite nicht bearbeitet werden an den Proxy zu schicken. Dafür wird die Url des Proxy direkt angegeben, und es wird die komplette Url der Anfrage direkt am Proxy angefragt:

  "proxy": "http://example.com:12345",

Bei dieser Konfiguration würde eine Anfragen an den eigenen Server in dieser Form „http://ownserver/api/v1/view/component“ an dem Proxy-Server in dieser Form überstetzt werden: „http://example.com:12345/api/v1/view/component“.

URL per Proxy

Um es etwas weiter zu spezifieren, kann man auch Url-Präfixe angeben, die explizit an den Proxy weitergeleitet werden. Dafür wird der Präfix und das Ziel angegeben:

  "proxy": {
    "/api": {
      "target": "http://example.com:12345",
      "ws": true
    }
  }

In diesem Fall werden nur noch Anfragen die mit „/api“ beginnen an den Proxy weitergeleitet, dabei bleibt die URL ebenso gleich wie beim „Single Proxy“.

Projekt verwalten

Nach dem nun das Projekt erstellt wurde und alle notwendigen Packete installiert sind, wird das Projekt nun im Visual Studio Code über „Datei -> Ornder öffnen“ geöffnet. Nach dem öffnen werden uns 3 Ordner und ein paar Dateien erscheinen:

node_moduleHierhin werden alle lokal installierten Packet abgelegt, welche über den „import“-Befehl eingebunden werden können
publicHier liegen die statischen Elemente, wie z.B. die index.html. Alles was direkt in der Index.html eingebunden werden soll, muss in diesem oder einem Unterordner gelegt werden
srcHier liegen die eigentlichen Quellen, die später die Anwendung definieren. Die noch zu erstellenden Unterordner sind eine häufig zu findene Konvention
src/componentsIn sich abgeschlossene Komponenten, für wiederkehrendes oder für Trennung von Hauptbestandteilen. Hier könnten z.B. Sidebar oder der Header liegen
src/containers
src/viewsDie Ansichten im Hauptfenster, die durch unterschiedliche URL’s angesteuert werden können

Private Packete

Zum Gliedern von Elementen kann man diese in Unterordner packen und mit einer „package.json“-Datei versehen, damit wird beim Import in den anderen Dateien nur noch der Unterordner angeben und alles weitere wird über die package.json definiert. Hier ein Beispiel einer solchen Datei:

{
  "name": "Sidebar",
  "version": "0.0.0",
  "private": true,
  "main": "./sidebar.jsx"
}

In diesem Fall wird das Packet mit den Namen „Sidebar“ betitelt und liegt in der Verison 0.0.0 vor. Der Parameter private sorgt dafür, dass diese Packet nur innerhalb des Projektes verwendet wird. Und welche Datei als Einstieg benutzt werden soll, wird über „main“ definiert, was in diesem Fall die sidebar.jsx ist.

Vorlage Themes

FAQ (oder Bootstrap und seine Tücken)

Fixed Header liegt über den Body

Damit bei einem Fixed Header der Content nicht hinter dem Header steht, muss am umschließenden Div bzw. Body vom Nav und Content ein „padding-top“ von „50px“ eingetragen.

seed auf MS SQL Tabellen ermitteln bzw. setzen

Um den SEED auf einer MS SQL Server Tabelle zu setzen, sind folgende Befehle notwendig:

dbcc checkident (<tblname>, reseed, <newMaxSeed>)

Ein Beispiel:

-- create table tblMy (nKey identity(1, 1), ...)
declare @maxKey int
select @maxKey = max(nKey) from tblMy
dbcc checkident (tblMy, reseed, @maxKey)

Hier noch ein Befehl, mit dem man alle aktuellen Seeds der vorhanden Tabellen sieht, die auch eine Identity-Spalte besitzten:

select Seed            = ident_seed(TABLE_NAME)
     , Increment       = ident_incr(TABLE_NAME)
     , CurrentIdentity = ident_current(TABLE_NAME)
     , Table           = TABLE_NAME
from   INFORMATION_SCHEMA.TABLES
where  objectproperty(object_id(TABLE_NAME), 'TableHasIdentity') = 1
and    TABLE_TYPE = N'BASE TABLE'

.Net und WebRequest mit Authentifizerung

WebRequest in C# abzusetzten ist mit den Bibliotheken recht einfach geworden. Aber wenn es dann mal mehr wird, als nur ein einfacher Download wird es schon wieder schwieriger. Daher hier eine kurze Anleitung, wie so ein Request bearbeitet wird.

Zuerst muss ein WebRequest erstellt werden:

var webReq = (HttpWebRequest)HttpWebRequest.Create("http://example.com/");

Dann muss unterschieden werden, ob es ein laden einer Website ist, oder ob senden von Daten an die Website ist. Bei laden einer Website wird häufig die GET-Methode verwendet, siehe hier:

webReq.Method = "GET"; // Ein einfache Get-Befehl, mit Parameter in der URL ala: example.com?param1=val1&param2=val2
// Request abschicken und Antwort auswerten 
try {
  // Beim GetResponse() fliegen die Fehlermeldungen, die der Server zurückgibt, wie 404 (Datei nicht gefunden) oder 401 (Nicht Authentifiziert)
  var webRes = (HttpWebResponse)webReq.GetResponse();
  // und nun den Stream lesen
  using (var streamer = webReq.GetResponseStream()) {
    // Hier kann man nun anhand von webRes.ContentType unterschiedlich die Daten verarbeitetn, z.B.: bei "text/xml" mit einem (new XmlDocument()).Load(streamer); alles in ein Xml-Objekt packen
  }
}
catch (WebException exc) {
  // Exceptions verarbeiten
}

Für die einfache übermittlung von Variablen mit der POST-Methode, hier noch ein Code-Schnipsel:

webReq.Method = "POST";
webReq.ContentType = "application/x-www-form-urlencoded";
// Variablen zusammenbauen und in Byte-Array wandeln um es auf den Stream schreiben zu können
var postData = "variable1=val1&variable2=val2";
var postBytes = Encoding.UTF8.GetBytes(postData);
// Länge der Daten mitgeben und diese nun auf den Stream schreiben
webReq.ContentLength = postBytes.Length;
var stream = webReq.GetRequestStream();
stream.Write(bytes, 0, bytes.Length);
// Request abschicken und Antwort auswerten (wie bei GET-Methode)
try {
  // Beim GetResponse() fliegen die Fehlermeldungen, die der Server zurückgibt, wie 404 (Datei nicht gefunden) oder 401 (Nicht Authentifiziert)
  var webRes = (HttpWebResponse)webReq.GetResponse();
  // und nun den Stream lesen
  using (var streamer = webReq.GetResponseStream()) {
    // Hier kann man nun anhand von webRes.ContentType unterschiedlich die Daten verarbeitetn, z.B.: bei "text/xml" mit einem (new XmlDocument()).Load(streamer); alles in ein Xml-Objekt packen
  }
}
catch (WebException exc) {
  // Exceptions verarbeiten
}

Dann gibt es aber noch die Probleme mit den Anmeldungen an dem WebServer, die mit folgenden Quellcode-Stücken gelöst werden können:

// Um die aktuelle Anmeldung zu benutzen (Häufig im Intranet möglich)
request.UseDefaultCredentials = true;
// Für eine explizite Netzwerkidentifikation (Via Domain)
request.Credentials = new NetworkCredential("username", "password");
// Für eine HTTP-Authentifizierung (Wird häufig via .htaccess parametriert)
var auth = Encoding.UTF8.GetBytes("user:password");
request.Headers["Authorization"] = "Basic " + Convert.ToBase64String(auth);
// Und ein Übel gibt es noch, wenn man einen Server besitzt der zwar mit SSL-Zertifikaten ausgestattet ist, aber
// keine Root-Zertifikate besitzt, kann mit nachfolgenden Code, mit diesen Server trotzdem reden:
ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
// Wobei hier zu bedenken ist, dass nun alle Zertifikate angenommen werden, man könnte hier noch eine passende Prüfung einbauen

Wenn Dateien an einen Website hochgeladen werden sollen, wird das ganze etwas schwieriger, daher habe ich dafür eine Klasse gebaut, die man unter nachfolgenden Link herunterladen kann: HttpFileUploader.
Hier noch eine Beispiel-Verwendung:

// Objekt erstellen
var fileUploader = new HttpFileUploader("http://example.com/upload");
// Parameter setzten
fileUploader.SetParam("LastModifiedSource", DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss"));
fileUploader.SetParam("Name", "ExampleName");
fileUploader.SetParam("Designation", "ExampleDesignation");
// XML-Datei setzten
var xmlfile = System.Text.Encoding.Unicode.GetBytes(xmlString);
fileUploader.SetFile("xmlfile", "xmlfile.xml", xmlfile, "text/xml");
// Bild setzen
fileUploader.SetFile("picture", "picture.png", pictureBytes, "image/png");
// Upload durchfuehren
var ret = fileUploader.SendRequest();

WordPress TinyMCE wieder aktivieren

Seit dem ich Markdown ausprobiert hatte, funktionierte mein TinyMCE-Editor nicht mehr. Nach langen suchen hab ich auch nicht wirklich was gefunden, immer nur Links auf TinyMCE Advanced Plugin.

Daher dachte ich, das ich mir das alte Plugin wieder suchen müsste, diese installieren und dann durch erneutes deaktivieren der TinyMCE wieder erscheint. Dabei bin ich dann aber auf des Rätsels Lösung gestoßen.

Ich musste das alte Plugin nicht installieren, sondern in meinen Profil, ist die erste Option wenn diese gesetzt ist, zum deaktivieren des TinyMCE vorhanden. Nach dem ich den Haken wieder entfernt habe, erscheint nun endlich der TinyMCE-Editor weider *freu*.

Umbau des Blogs

Guten Tag Leser

Der Blog wird aktuell umgebaut.

Zuerst wird ein Strukturierender Umbau durchgeführt. Alles was als KnowHow gehandelt wird, wird ab sofort in die Wissensdatenbank eingetragen, damit die Artikel einfach zu finden sind. In den Standard-Blog kommen dann noch Eintrage die mehr an Meldungen erinnern.

Nachfolgend wird noch ein neuer Style auf HTML5 und CSS3 kommen wird, da dieser nicht gekauft wird, sondern von mir selbst gebaut wird, dauert dies noch etwas bis er komplett funktionstüchtig ist und für alle aktiviert wird.

Mfg MDN

CSS und seine Vielfalt

Da ich mich nun in der Arbeit wieder mehr mit Webseiten beschäftigen muss, bin ich zurzeit auf viele gute Webseiten zu CSS und HTML gefunden. Als interessantes fand ich folgenden URL: Sprite-Grafik / Webstandard. Solche Menus kenne ich nur per JavaScript, welches ich ungern einsetze, aber jetzt weiß ich auch wie es per CSS geht. Dies werde ich woll merken und in meine Nächsten Templates einbauen :-).

Nachfolgende URLs sind ebenfalls noch zu nennen:

Akismet-Plugin in Deutschland verwenden

Durch Suche für Custom Post Types bin ich auf folgenden Artikel gestoßen: Hinweise zum Datenschutz beim Einsatz von Akismet in Deutschland.

Da ich bis jetzt nur gute Arbeit vom Akismet kenne, und das Plugin nicht deaktiveren möchte habe ich mich dazu entschieden das Plugin „Akismet Privacy Policies“ zu aktivieren, wodurch jetzt an jeder möglichen Stelle für Kommentar die Checkboxen erscheint, aber leider geht es nicht anders.

Dateien direkt über FTP mit Notepad++ editieren

Da ich gerne mit Notepad++ arbeite und ich letztens mal wieder an meiner Website weitermachen wollte, habe ich mich daran errinnert das ich mit Notepad++ früher direkt auf dem FTP-Server arbeiten konnte. Diese Funktionalität habe ich dann auch etwas länger gesucht aber nicht mehr gefunden. Im Internet bei Notepad++ bin ich dann auf die Seite der Plugins auf des Rätsels Lösung gestossen. Es war der FTPExplorer der aber leider nur die ANSI-Version unterstütz und da ich Unicode benutze ist das Plugin deaktiviert. Aber eine Zeile tiefer dann Lösung meines Problems, dass FTP_synchronize Plugin.

Einfach herunterladen und die DLL ins Plugin Verzeichnis kopieren.  Notepad++ starten. Über das Menü „Erweiterungen->FTP_synchronize->Show FTP Folders“ wird auf der rechten Seite der FTP_synchronize angezeigt. Über den 7. Button „Open settings dialog…“ wird der Konfigurationsdialog für die Verbindungen geöffnet, die zuerst eingerichtet werden müssen, danach kann man über den 1. Button „Connect“ die Verbindung zu dem Server aufbauen.

Wichtig beim Profile anlegen ist, dann man zuerst auf New (links unten) klickt, danach das Profile anwählt ihm einen Namen (Eingabefeld rechts oben) gibt und dannach auf Rename (Schaltfläche daneben) klickt. Danach kann man alle weiteren Einstellungen für den FTP-Zugang eingeben und muss unbedingt danach auf Apply (rechts unten) klicken, ansonst sind die Änderungen verloren.

Logging auf Debian

Die Einstellungen fürs Logging liegen unter /etc/syslog.conf. Um Änderungen zu übernehmen muss dieser Befehl ausgeführt werden:

invoke-rc.d sysklogd restart

Speziel zum Postfix sollten follgende Einstellungen getroffen werden:

Keine Anzeige mehr im syslog durch änder der 1ten in die 2te Zeile:
*.*;auth,authpriv.none -/var/log/syslog
*.*;auth,authpriv,mail.none -/var/log/syslog

Alle Mail-Logs in eine Datei mail.log
mail.* -/var/log/mail.log

Keine Doppeltes aufzeichnen deswegen diese Zeilen auskommentieren
#mail.info -/var/log/mail.info
#mail.warn -/var/log/mail.warn
#mail.err /var/log/mail.err

Information kommen von http://lemmingzshadow.net/16/postfix-logging-auf-debian-etch/

SysCP und MailServer

Da ich immer mal wieder Probleme bei meine Postfix-Server hatte, wenn ich zeitgleich die Domain in der main.cf unter mydestination angegeben hatte und zeitgleich im syscp als Virtuellen Host kamm immer wieder diese Fehlermeldung im Postfix auf:

warning: do not list domain <DOMAIN> in BOTH mydestination and virtual_mailbox_domains

Desweiteren hatte ich auch das Problem, das wenn ich eine Mail an root@<DOMAIN> geschrieben hab, dann ist diese Mail in die Datei /var/mail/root gewandert und nicht als Datei in den Ordner der virtuellen Hosts, wodurch ich sie nicht per IMAP abrufen konnte. Darauf hin hab ich nun meine Configs dahingehen geändert das ich zuerst in der main.cf dies stehen hab:

myhostname = <DOMAIN>
mydomain = $myhostname
myorigin = $myhostname #oder /etc/mailname, ist das gleiche da es nur den Domainname beinhaltet
mydestination = localhost.$mydomain, localhost

in der /etc/aliases wird alles auf root geschoben und root wird entfern, durch den myorigin-Parameter wird da automatisch ein Full-Quallified-Name draus:

postmaster: root
hostmaster: root
webmaster: root
#root: root@<DOMAIN>

Im  Syscp müssen dann jetzt noch entsprechend für postmaster, hostmaster und webmaster die Konten besser Weiterleitungen eingerichtet werden. Und das Email-Konto root muss noch angelegt werden, damit er die Mails empfangen kann.