Marco Rico Gomez | Weigle Wilczek GmbH

Leichtgewichtige Webanwendungen mit
dem MEAN Stack
Agenda
●

Überblick MEAN-Stack
–

●

Warum?
–

●

Architektur einer modernen Webanwendung
Was spricht für diesen Technologiestack

Wie?
–
–

Datenmodell und -speicherung

–
●

Der Server
Frontend

Tooling
Was ist der MEAN Stack?
●

●

Technologiestack für die Entwicklung von
Webanwendung
Valeri Karpov, April 2013
M

E

A

N
Architektur
Warum?
Eine Programmiersprache
MongoDB
db.foo.find({ foo: 'bar' });

Node.JS/ Express.JS
app.get('/api/foo/:bar', function (req, res, next) {
res.send({ foo: 'bar' });
});

AngularJS:
angular.controller('FooCtrl', function ($scope, $resource) {
var Foo = $resource('/api/foo/:bar', { bar: '@id'});
$scope.bar = Foo.get({bar: 'bar'});
});
Ein Datenformat (JSON)
{
"title": "Foo Bar",
"type": 12
}

{
"title": "Foo Bar",
"type": 12
}

{
"title": "Foo Bar",
"type": 12
}
Keine Schemamigrationen

ALTER TABLE foo ADD COLUMN bar
VARCHAR(200) NOT NULL;

Schema wird in der Anwendung definiert.
Geringer Resourcenverbrauch
●

kein (wenig) UI-Rendering auf dem Server

●

ereignisgesteuerte Architektur / Non-blocking I/O
Wie?
app.js
// declare module dependencies ...
var express = require('express');
// more ...
var app = express();
// configure express ...
app.use(express.logger('dev'));
app.use(express.bodyParser());
app.use(app.router);
// more ...
// define routes ...
app.get('/', routes.index);
app.get('/users', user.list);
// ... and go!!
http.createServer(app).listen(app.get('port'), function() {
console.log('Express server listening on port ' +
app.get('port'));
});
Express API (HTTP Verben)
●

app.get(path, [callback...], callback)

●

app.post(path, [callback...],callback)

●

app.put(path, [callback...], callback)

●

app.delete(path, [callback...],callback)

●

...

callback = function (req, res, next) {
…
}
Routen sind einfache Funktionen

app.get('/api/foo', function (req, res) {
res.send({ foo: 'bar' });
});
Routen filtern (Wildcards)

app.all("/app/*", function (req, res, next) {
if (isUserLoggedIn) next();
else res.redirect('/login');
});
Routen (Variablen)

app.put("/api/task/:id", function(req, res, next) {
res.send("Your request id: " + req.params.id);
});
MongoDB
{

}

"name": "Create something beautiful",
"dueBy": Date(2013, 10, 1),
"priority": 2,
"done": false,
"subTasks": [
{
"name": "blabla",
"done": true,
},
{
"name": "blabla",
"done": false
}
]
dokumentenorientiert
schemafrei
Join-less
{
"name": "Create something beautiful",
"dueBy": Date(2013, 10, 1),
"priority": 2,
"done": false,
"subTasks": [
{
"name": "blabla",
"done": true,
},
{
"name": "blabla",
"done": false
}
]
}

verschachtelte Datenstrukturen
16 MB Limit beachten !
Adhoc-Abfragen
db.tasks.find({
done: false,
dueBy: {
$gte: new Date(2013, 10, 1),
$lt: new Date(2013, 11, 1)
},
priotity: { $in: [0, 2] },
subTasks: { $exists: true }
}).sort({dueBy: -1}).limit(10);
Mongoose
var mongoose = require('mongoose');
var Task = mongoose.model('Task', {
name: { type: String, required: true },
done: { type: Boolean, default: false },
dueBy: Date,
priority: Number
});
Validierung

Task.schema.path('priority')
.validate(function (value) {
return (value >= 0 && value <= 2)
}, 'Invalid priority');
Validierung
{
"message": "Validation failed",
"name": "ValidationError",
"errors": {
"priority": {
"message": "Validator failed for ...",
"name": "ValidatorError",
"path": "priority",
"type": "Invalid priority",
"value": 4
}
}

Detaillierte Fehlerinformationen
Einfach, diese generisch im Client anzuzeigen
RESTful APIs erstellen

app.post('/api/tasks', function(req, res) {
var newTask = new model.Task(req.body);
newTask.save(function (err) {
if (err) return res.send(422, err);
res.send(201);
});
};
AngularJS
●

clienseitiges JavaScript Framework für WebApps.
–

Templates

–

Model-View-Controller

–

Dependency Injection

–

Data-Binding

–

Direktiven

–

Views und Routen
Bootstrapping Angular
<!doctype html>
<html lang="en" ng-app="demo">
<head>
...
</head>
<body ng-init="hello='Hello World'">
{{ hello }}
<script src="assets/angular.js"></script>
<script>
// separate file(s) (!)
angular.module("demo", []);
</script>
</body>
</html>
Bootstrapping Angular (2)
<!doctype html>
<html lang="en" ng-app="demo">
<head>
...
</head>
<body ng-init="hello='Hello World'">
Hello World
<script src="assets/angular.js"></script>
<script>
// separate file(s) (!)
angular.module("demo", []);
</script>
</body>
</html>
Templates & Databinding
Direktiven
●
●
●
●
●
●
●
●

ng-include
ng-click
ng-hide/ ng-show
ng-class
ng-cloak
ng-repeat
ng-model
…
Scopes & Controllers

angular.controller();
Client-side Services
●

Services sind Singletons
–
–

●

kapseln Funktionalität
können mittels Angular DI injiziert werden.

Built-in
–

$http, $window, $document, $filter, ...

angular.factory(„myService“, function() {});
Dependency Injection

function DemoCtrl ($scope, $resource) {
...
}
RESTful APIs konsumieren
●

ngResource Modul
–

Support für Zugriff auf RESTful APIs

–

$resource-Service
●
●
●
●

query()
get()
save()
delete()
HTML erweitern (Direktiven)
●

eigene Komponentenen definieren
–

●

DOM-Transformation

vorhandene Elemente um neues Verhalten
erweitern

angular.directive();
Direktiven (2)
●

eigene Komponenten erstellen (don't repeat your
self)
Direktiven (3)
●

angular-ui Projekt
–

ui-bootstrap (Accordion/ Tabs/ Alerts/ Carousel)

–

ng-grid

–

ui-router

–

select2

–

codeMirror

–

...

http://angular-ui.github.io/
Tooling

http://yeoman.io
Q&A

rico@weiglewilczek.com

@mricog

Leichtgewichtige Webwenwendungen mit dem MEAN-Stack

Editor's Notes

  • #3 ca. 1 min.
  • #4 Kein Produkt oder Standard! Sammlung von Technologien für den Entwicklung von Webanwendungen Anlehnung an LAMP-Stack. Begriff wurde erstmals von Valeri Karpov im April 2013 in einem Blogpost erwähnt.
  • #5 MongoDB: 2007 / 2010 (prod ready) Express: (932 SLC + 1143 SLOC) AngularJs: 2009 Node.js: 2009
  • #6 Single-Page Applikation UI-Logik wird vom Client berechnet Server ist zustandslos und liefert nur Daten HTML Templates, JS, CSS usw. können separat von einem WebServer geliefert werden.
  • #7 Welche Gründe sprechen für den MEAN-Stack?
  • #8 JavaScript „Die Sprache des Webs“ Alle Entwickler sprechen die gleiche Sprache „Don&apos;t repeat yourself“. Zahlreiche JavaScript Bibliotheken können sowohl auf dem Client als auch auf dem Server verwendet werden
  • #9 Einheitliches Datenformat Client/Server und Datenbank sprechen JSON.
  • #42 Yeoman: Workflow tool / Scarfolding für WebApps. Grunt: Build-System für JavaScript Bower: PackageManager für clientseitige JavaScript Bibliotheken. Mocha: Testframework für JavaScript