Share
Embed
Transcript
96 slides
-
Agenda 8:30 Uhr: Registrierung 9:30 Uhr: Beginn des Workshops Theorie:
Ereignisgesteuerte Architektur, Grundlagen, NPM 11:00 - 11:15 Uhr: Kaffeepause Streams, Dateisysteme 12:30 - 13:30 Uhr: Mittagessen Web Applikation mit Node.js und Express 15:00 - 15:15 Uhr: Kaffeepause Testen mit Node.js / Tooling Ca. 17:00 Uhr: Ende 2 -
Who am I? { "name": "Martina Kraus", "working": ["Software-Developer at
Onwerk GmbH", "lecturer at HS Mannheim / HS Karlsruhe"], "technologies": ["javascript/ ecmascript", "node", "docker", "nosql-databases" ], "others": ["founder of RheinNeckarJS and Docker Mannheim Meetup", "Member of Hackerstolz e.V"] } 3 -
Was ist NodeJS? (In a nutshell) • Node.js === JavaScript
Engine + JavaScript Framework • v6.11.0 LTS • V8.1.2 Latest Features • Entwickelt von Ryan Dahl 2009 (Mittlerweile Joyent Inc.) • Google V8 Engine (mittlerweile aber auch mit Chakra) • Ausgelegt für viel I/O • Event-Driven Architecture • Asynchron 6 -
JavaScript Engines 7 Engine Application V8 Chrome, Node.js Chakra Microsoft
Edge, Node.js SpiderMonkey Firefox JScript IE JavaScriptCore WebKit, Safari Rhino Java Platform -
Getting started - Installation • https://nodejs.org/en/download/ • Windows Installer /
Binaries • Mac OS X Installer / Binaries • Linux Binaries (.tar .gz) • Sourcecodes zum selber kompilieren (Abhängig von Python 2.6/2.7) 9 -
Getting started - NVM • Node Version Manager ◦ Unterschiedliche
Versionen parallel installieren ◦ Keine administrativen Rechte curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.2/install.sh | bash Nvm install 6 //installiert die latest node 6 Version Nvm use 6 // switchen zu einer anderen node Version 10 -
Getting started - Hello EnterJS • Über Node.js shell: (Read-eval-print-loop)
◦ Nicht geeignet fuer echte Applikationen • Node.js Anwendung: ◦ JavaScript Datei erstellen (index.js) ◦ Mithilfe von node aufrufen: $ node index.js 11 -
Core Module • Bringt einige Core Module mit: ◦ http,
net, fs, crypto, buffer • Einbindung eines Moduls: const http = require(‘http’); const http = require(‘fs’); • Fuer alles andere: Node-Package-Manager 12 -
NPM • Wird mit der Installation mitgeliefert • Abhängige Module
können in einem JSON-File definiert werden: package.json • Dieses wird mit npm init initialisiert 13 -
Package.json { "name": "node-js-sample", "version": "1.1.", "description": "A sample Node.js
app using Express 4", "main": "index.js", "scripts": { "start": "node index.js" }, "dependencies": { "express": "^4.13.3" }, "devDependencies": { "mocha": "^4.13.3" }, "license": "MIT" } 14 -
NPM • Installieren von Npm-Modulen (und deren Abhängigkeiten) : $
npm i(nstall) <modulName> $ npm i(nstall) --save <modulName> (Eintrag in Package.json) $ npm i(nstall) --save-dev <modulName> (Eintrag in Package.json) • Installieren von globalen Modulen $ npm i(nstall) -g <modulName> 15 -
node_modules • Dort werden alle via npm installierten Packete abgelegt.
• Jedes Projekt hat seinen eigenen node_modules Ordner 1. Node Core Module 2. npm-Module 3. Selbst Geschriebenen Module (lokale Dateien) 16 -
Module • Anwendungen in logische Teile Blöcke (Module) aufspalten) •
Einzelne Module können wiederverwendet werden • Leichter zu testen (Unit-Tests) • Strukturierung des eigenen Sourcecodes 17 -
Module in Node.js • Inkludieren von eigenen Modulen: const myModule
= require(‘<path-to-module>/myModule’); • Module Verfuegbar machen: module.exports = myModule; 18 -
Do it yourself!!! 20 • Schreibe ein Taschenrechner-Modul (plus /
minus / geteilt / multipliziert) • Dieses Modul soll in eine app.js importiert werden und wie folgt genutzt werden: console.log(calculator.add(number_one, number_two)); console.log(calculator.divide(number_one, number_two)); console.log(calculator.multiply(number_one, number_two)); console.log(calculator.substract(number_one, number_two)); -
Node.js Architektur • Ausgelegt für viel I/O ◦ Prinzip der
Nicht blockierende I/O ◦ Asynchron (Callbacks) • Ereignisgesteuerte Architektur 21 -
Traditionelles I/O (synchron) var db_result = db.query(“select * from table“);
doSomething(db_result); //wait! doSomeOtherVoodoo(); //blocked 22 -
Non-blocking I/O (asynchron) db.query(“select * from table“,function(db_result) { doSomething(db_result); //wait
}); doSomeOtherVoodoo(); //don’t have to wait 23 -
Callback Konzept (in a nutshell) • Funktionen sind Objekte, •
Sie können als Parameter einer anderen Funktion übergeben werden. • Funktion zur Auswertung wird direkt mitgegeben, • Verhindern das blockieren von Programmen 24 -
Verarbeitung von Requests • Prozessmodell (Apache 1.x) • Threadmodell (Apache
2.x) • Event-Driven Architecture (NodeJS und Nginx) 25 -
Event-Loop 26 • Selbstgeschriebene Programme in Node.js laufen “Single-Threaded” •
Node.js läuft asynchron ◦ Mit setTimout() kann allerdings ebenso blockiert werden • Node.js Applikationen laufe in einer Event-Loop ◦ Wartet auf Events ◦ Triggert eine Callback Funktion -
EventEmitter 32 • Node.js Core Module • lauschen auf Events:
eventEmitter.on('data_received', function(){ console.log('data received succesfully.'); }); • feuern von Events eventEmitter.emit('data_received'); -
File System • Node Core Modul fs const fs =
require(‘fs’); • Ermöglicht den Zugriff auf Dateien und Ordner • Verzeichnisse Lesen (synchron und asynchron) fs.readdirSync || fs readdir • Dateien Lesen (synchron und asynchron) fs.readFileSync || fs readFile 34 -
path-Modul • Node Core Modul fs const path = require(‘path’);
path.join(): fügt Pfade plattformunabhängig zusammen 35 -
Globale Objects • __dirname ◦ Verzeichnis der aktuellen Datei •
__filename ◦ __dirname + Name der aktuellen Datei • process.cwd ◦ Aktuelle Arbeitsverzeichnis 36 -
Dateien schreiben fs.writeFile(); fs.writeFileSync(); • Falls Error während dem Schreiben:
◦ Kein “all or nothing” ◦ Halb-fertige Datei ◦ Abhilfe durch voriges umbenennen 37 -
Informationen über Datei auslesen fs.stat(); • Liefert Meta-Informationen über eine
Datei: ◦ Größe ◦ Aktualisierungs-Datum ◦ Erstellungsdatum 38 -
Do it yourself!!! 39 • Erstelle eine Datei test.txt mit
folgendem Inhalt: “EnterJS rockz” • Schreibe die Meta-Informationen des Files test.txt in eine neue Datei mit dem Namen “meta_test.txt” -
Streams • Kontinuierlicher Fluss an Daten • Größe und Ende
ist im Voraus nicht bekannt • Streams ähneln Arrays • Haben eine zeitliche Reihenfolge • Verarbeitung von größeren Dateien moeglich 40 -
Streams • Jeder Stream ist eine Instanz des EventEmitters •
Node bietet vier unterschiedliche Streams an: ◦ Readable: für Lese-Operationen ◦ Writable: für Schreiboperationen ◦ Duplex: für Lese- und Schreiboperationen ◦ Transform: duplex-stream, bei dem der Output abhängig von dem Input ist 41 -
Readable-Streams • Events: ◦ data: Sobald Daten gelesen werden können
◦ end: Sobald der Datenstrom beendet ist readableStream.on(‘data’, callback) readableStream.on(end, callback) 42 -
Writeable-Streams • Funktionen: ◦ write: schreiben in den Stream ◦
end: beenden des Streams writeableStream.write(‘data’) //return true oder false writeableStream.end() 43 -
Writeable-Streams (Synchronisierung) • Problem-Szenario: ◦ Readable Stream übergibt Daten an
den Writable Stream (Lesen ist schneller als schreiben) ◦ Schreibpuffer läuft über -> Datenverlust ◦ Readable Stream mit pause() anhalten. ◦ Event: drain, sobald Writable Stream wieder Daten aufnehmen kann ◦ Readable Stream mit resume() fortsetzen 44 -
Duplex-Stream • Ein “Behälter” für writeable und readable Streams •
Beide Streams in einem Objekt • Eher selten • Streams sind unabhängig voneinander 46 -
Transform-Stream • Ein “Behälter” für writeable und readable Streams writableStream
-> Transformation / Manipulation -> readableStream, 47 -
Do it yourself!!! 48 • Implementiere folgendes Szenario mit Streams:
◦ Eine Datei input.txt wird eingelesen ◦ Die Daten der eingelesenen Datei sollen in eine neue Datei output.txt geschrieben werden ◦ Beachte hierbei die Synchronisation der Daten ▪ drain-event ▪ const isReady = writerStream.write(data,'UTF8'); -
Web APIs - Früher • Serverseitiges rendering, statische Webseiten •
Das gesamte HTML wird immer mit übertragen • Viele Daten -> viel Netzwerktransfer • Keine Offline Fähigkeit 50 -
Web APIs - Heute • Reine Datenübertragung (meist JSON) •
HTML wird clientseitig gerendert • Daten werden via JavaScript in das HTML gemerged • Entlastung des WebServers 52 -
Web APIs - Heute • REST API, HTTP API, ***
API • Kleine Modulare Service-Schnittstellen • Services können sich gegenseitig aufrufen • Sicherheit über Authentifizierungs-Token • Jeder Client der HTTP spricht kann mit dem Service interagieren 53 -
Web APIs - Basics • HTTP Verben ◦ GET: Lädt
Daten von einem WebServer ◦ PUT: Aktualisiert Daten auf einem WebServer ◦ POST: Legt neue Daten auf einem WebServer an ◦ DELETE: Löscht Daten auf einem WebServer • HTTP Web server • Uniform Resource Locator URL 54 -
Web APIs - Schnittstelle Beispiel: https://localhost/api/v1/blog/11 Eindeutiger Bezeichner der Datei/
Ressource GET lädt Blogartikel mit der Id 11 PUT aktualisiert den Blogartikel mit der Id 11 DELETE löscht den Blogartikel mit der Id 11 POST legt einen Blogartikel an (in dem Fall würde keine Id benötigt werden) 55 -
Web APIs - Schnittstelle 56 Mehr Beispiele: • GET /api/blog
- gets all blog articles • DELETE /api/user - deletes all users Filterung via Queryparameter: • GET /api/blog?search=cat - get all blog articles with its content “cat” • GET /api/blog?orderBy=date&direction=desc - get all blog articles ordered by date descending • GET /api/blog?page=3 - gets the third page -
Web APIs - Anforderung an WebServer • APIs zur Verfügung
stellen. • Routingschema der URL != Ordnerstruktur des WebServers ◦ Mapping der Routen auf die Ressourcen ◦ Client gibt via MIME Type an wie er die Daten haben möchte (JSON, XML) ◦ Server muss die Ressourcen dementsprechend umwandeln. • Unterstützung aller HTTP Methoden 57 -
HTTP-Modul • Node.js Core Modul • API zur Implementierung eines
WebServers const server = http.createServer(requestHandler); server.listen(1337, ‘127.0.0.1’); 58 -
HTTP-Modul function requestHandler(request, response) { res.statusCode = 200; res.setHeader('Content-Type', 'text/plain');
res.end('Hello World\n'); } 59 -
Express • Serverseitiges Web Application Framework für Node.js • Entwickelt
von Douglas Christopher Wilson and community • Aktuelle Version: 4.0 (MIT License) • Erweitert Node.js an Funktionalität ◦ Ausliefern statischer Dateien (CSS/ JS/ HTML) ◦ Routing ◦ Aufbau des Response 60 -
Simple WebServer mit Express const express = require('express'); const app
= express(); app.get('/', function(req, res) { res.end('Hello World!') }); app.listen(1337); 61 -
Simple WebServer mit Express Laden des Moduls Express in der
JavaScript-Server Datei var express = require('express') var app = express(); Requesthandler wenn ein Request mit der HTTP-Methode GET für die URL localhost/home eingetroffen ist app.get('/home', function(req, res) { res.end('Hello World!') }) 62 -
Request Objekt API 70 Attribut Beschreibung req.baseUrl URL zur Ressource
req.body Request Body req.cookies Client Cookies req.hostname Host name des HTTP Headers req.params Alle Url-Parameter req.get(<http-header-key>) req.get(‘content-type’) -
Response Objekt API 71 Attribut Beschreibung res.end Beendet einen Response
ohne Body res.status Setzen des Http-Statuscode res.json Sendet einen json-Body res.send([body]) Sendet Reponse mit einem Body res.set(<http-resoonse-header>) res.set('Content-Type', 'text/plain'); res.redirect Redirect zu angegebenem Pfad -
Express Middleware • Bearbeitet den Request bevor an die Requesthandler
gegeben wird • Können selbst geschrieben werden ◦ Express bietet allerdings einige an app.use("/login", webguiMiddleware); app.use("/login", versionMiddleware); app.use("/weather", versionMiddleware); 72 -
Ausliefern statischer Dateien Konfiguration der Express-App app.use(express.static(path.join(__dirname, "public"))); Mit app.use
können Express-Parameter zur Konfiguration übergeben werden path: NodeJS Core Modul für Handling von Applikationspfäden. const path = require("path"); path.join([path1][, path2][, …]) //Konkatenation der strings express.static(<dirname>); Gibt an unter welchem Dateipfad die statischen Dateien zu finde sind. (hier: /applicationRootPath/public/) 73 -
Middleware: Body-Parser • Wichtig bei PUT und POST-Methoden • Ist
in req.body gespeichert • Der Request Body beinhaltet nur Key-Value Paare ◦ Schlecht auszulesen (kein Objekt) ◦ Kein encoding ◦ Keine “Konfigurationsmöglichkeiten” des Bodys 74 -
Weitere Express middleware 76 cookie-parser Formatierung des Request-Cookies compression Komprimierung
des HTTP Response cors Aktiviert cross-origin resource sharing serve-favicon Liefert das Favicon aus session Stellt eine Session her -
Do it yourself!!! - WebAPI 77 • https://github.com/CodeKittey/node_workshop_enterJS • ExpressExercise
1. Schreibe einen WebServer der für die Route ‘/’ die Datei index.html ausgibt. 2. Schreibe ein WebAPI mit Express mit folgenden Routen: -
Do it yourself!!! - WebAPI 78 GET /api/v1/players Liefert alle
auf dem Server gespeicherten Spieler GET /api/players?favorites=true Liefert alle auf dem Server gespeicherten Spieler, welche als Favorit markiert wurden GET /api/players?search=<char> Liefert alle auf dem Server gespeicherten Spieler die mit dem Anfangsbuchstaben (Nachnamen) beginnen welcher mit hilfe des search Flags in der URL mitgegeben wird ( kann hierbei Werte von A-Z annehmen) -
Node.js Development Tools • Eslint (statische Code Analyse) • Mocha/
Jasmine/ Karma/ Protactor (Unit Tests) • Grunt/ Gulp/ Webpack (Bundling) 80 -
Eslint • Tooling zur statischen Code Analyse Installation: $npm install
eslint --save-dev $npm install -g eslint • Regeln zur Analyse werden in einer .eslintrc Datei festgelegt $eslint --init //.eslintrc Datei wird erstellt (mit Default Rules) 81 -
Eslint - Regeln • Vollständiges Regelset: ◦ http://eslint.org/docs/rules/ $eslint app.js
//app.js wird anhand definierter Regeln geprüft $eslint --fix app.js //app.js wird anhand definierter Regeln geprüft und teilweise //automatisch korrigiert 82 -
Do it Yourself!!! • Unter /tools/ ist eine .eslintrc Datei
zu finden. • Überprüfe deine JavaScript-Files für WebAPI mithilfe von Eslint 83 -
Eslint für IDEs • Atom: ◦ https://atom.io/packages/linter-eslint • WebStorm: ◦
https://plugins.jetbrains.com/plugin/7494-eslint • Sublime: ◦ https://github.com/roadhump/SublimeLinter-eslint • Visual Studio Code ◦ https://marketplace.visualstudio.com/items? itemName=dbaeumer.vscode-eslint 84 -
.eslintignore • Auflistung von Ordnern und Dateien die nicht mit
geprüft werden sollen • Aehnlich dem .gitignore Konzept • node_modules werden hierbei automatisch ignoriert 85 -
Testen mit Node.js • Test runner: mocha, tape, protector •
Assertion Library: chai, assert • Test Setup (Erstellung Mock-Objekte): sinon 86 -
Mocha • Umfassendes Test framework • Ermöglicht asynchrones Testen •
Modultests • Testen von WebAPIs $ npm install -g mocha $ npm install --save-dev mocha 87 -
Mocha - Assertion • Vergleiche mithilfe assertion libraries: ◦ Should.js
◦ Expect.js ◦ Assert.js • Assertion Library Chai kombiniert alle drei Libraries 88 -
Chai • BDD / TDD Assertion Library für node.js $
npm install --save-dev chai doo.should.be.a('string'); doo.should.equal('bar'); doo.should.have.lengthOf(11); tea.should.have.property('flavors') .with.lengthOf(3); 89 -
Testen von WebAPIs • chai-http $ npm install --save-dev chai-http
const chai = require('chai'); const chaiHttp = require('chai-http'); const should = chai.should(); chai.use(chaiHttp); 90 -
Testen von WebAPIs • Testen eines Get-Requests: chai.request(server) .get('/api/v1/players') .end((err,
res) => { res.should.have.status(200); res.body.should.be.a('array'); res.body.length.should.not.be.eql(0); done(); }); 91 -
Testen von WebAPIs • Testen eines Post-Requests: chai.request(server).post('/players) .send(employee) .end((err,
res) => { res.should.have.status(201); res.body.should.be.a('object'); res.body.id.should.be.a('string'); done(); }); 92 -
Hooks 93 describe('hooks', function() { before(function() { // runs before
all tests in this block }); after(function() { // runs after all tests in this block }); beforeEach(function() { // runs before each test in this block }); afterEach(function() { // runs after each test in this block }); // test cases }); -
Do it yourself • Unter TDD_Exercise befindet sich eine server.js-Datei
und eine Passende Test-Datei. 1. Schreibe zuerst die Tests zu den jeweiligen Routen 2. Implementiere den WebServer 94 -
Nuetzliche Links • http://nodejs.org/download/ (Node.js Homepage) • https://www.joyent.com/noderoad (next Steps
Node.js) • https://github.com/creationix/nvm/blob/master/README.md • http://nodeschool.io/ (Tutorials) • https://www.npmjs.org (Node packaged Modul – Packed Manager) 96