PLAN


  • Node.js
  • Frameworks & Libs
  • Demo application

Node.js


                                              is bad for:

  • CPU heavy tasks
  • Doing everything with Node

NODE.JS


                                                           is good for:

  • Prototyping
  • REST / JSON APIs
  • SPA
  • Streaming data
  • Real-time apps

MODULES


Node Package Manager

~55k modules available


NPM

 npm install express npm install express -g npm install express --save npm install nodemon --save-dev

PACKAGE.JSON

 {
  "name": "application-name",
  "version": "0.0.1",
  "private": true,
  "scripts": {
    "start": "node app.js"
  },
  "dependencies": {
    "express": "3.4.8",
    "jade": "*"
  },  "devDependencies: {  }
 }
 npm publish <tarball> npm publish <folder>

HTTP Server


 var http = require('http');
http.createServer(function (req, res) { res.writeHead(200, {'Content-Type': 'text/plain'}); res.end('Hello World!'); }).listen(3000);
 node server.js

WHAT's INSIDE


  • HTTP, HTTPS & TCP interfaces
  • File System I/O
  • Streams
  • Child Process
  • Cluster
  • . . .

NETWORK INTERFACES


HTTP/HTTPS/TCP

 // require a module
var server = http || https || net;
server.createServer([requestListener]).listen(port, [callback]);

FILE SYSTEM I/O


 var fs = require('fs');
fs.readFile(filename, [options], callback); fs.readFileSync(filename, [options]);
fs.writeFile(filename, data, [options], callback); fs.writeFileSync(filename, data, [options]);
fs.rmdir(path, callback); fs.unlink(path, callback); fs.readdir(path, callback);

STREAMS


  • Readable (req, fs, stdout, stderr)
  • Writable (res, fs, stdin)
  • Duplex (TCP sockets, crypto)
  • Transform (zlib, crypto)

STREAMS USE CASE


 http.createServer(function (req, res) {   fs.readFile(__dirname + '/file.txt', function (err, data) {     res.end(data);   }); });

VS

 http.createServer(function (req, res) {   var stream = fs.createReadStream(__dirname + '/file.txt');   stream.pipe(res); });

CHILD PROCESS

 var cp = require('child_process'); cp.spawn(command, [args], [options]); cp.exec(command, [options], callback); cp.execFile(file, [args], [options], [callback]);
cp.fork(modulePath, [args], [options]);
 child.stdin  // Writable stream child.stdout // Readable stream child.stderr // Readable stream
// Sync, used with 'forked' process only child.send(message); child.on('message', callback);

CLUSTER

 var cluster = require('cluster'),     http = require('http'),
numCPUs = require('os').cpus().length;

if (cluster.isMaster) {
for (var i = 0; i < numCPUs; i++) {
cluster.fork();
}
} else {
http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('Hello World!');
}).listen(3000);
}

PROTOTYPING


MEAN stack

MongoDB + Express + AngularJS + Node.js





EXPRESS


  • Middleware system
  • Router
  • Templating (Jade, EJS)

 npm install -g express express appname

SETTING UP


 var express = require('express'),     app = express();
app.set('port', process.env.PORT || 3000); app.set('view engine', 'jade'); app.set('views', __dirname + '/views');
app.use(express.bodyParser()); app.use(express.methodOverride()); app.use(app.router); app.use(express.static(path.join(__dirname, 'public')));
app.listen(app.get('port'));

MIDDLEWAREs


 app.use(function (req, res, next) {  // Do something...  next(); // Call next middleware });
var middleware = function (req, res, next) { // Do something... next(); // Call next middleware};

ROUTES


 app.get('/', function (req, res) {   res.render('index'); });
app.get('/user', middleware, function (req, res) { res.render('user'); // Render page for authorized users only });

ERROR HANDLING


Custom Errors

 var AuthError = function (msg) {   Error.call(this);   Error.captureStackTrace(this, arguments.callee);   this.message = msg;   this.name = 'AuthError'; };
AuthError.prototype.__proto__ = Error.prototype;

Error Handling


Error Middleware

 app.use(function (err, req, res, next) {   if (err.name == 'AuthError') {     res.send(401, {error: err.message});   } });
 var middleware = function (req, res, next) {   if (req.body.password != 'password') {     return next(new AuthError('Unauthorized'));   }   next(); };

Mongodb


Document-Oriented BSON data storage

+ Mongoose ODM


 var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/dbname');

Mongoose Schemas

 var Schema = require('mongoose').Schema;
var UserSchema = new Schema({ username: { type: String, unique: true, required: true }, comments: [{body: String, date: Date}], modified: { type: Date, default: Date.now }, role: String }); var User = mongoose.model('User', UserSchema);

CRUD


 var user = new User(data); user.save(function (err, user) {}); User.find(function (err, users) {}); User.find({role: 'Moderator'}, function (err, users) {}); User.findOne({username: 'user'}, function (err, user) {}); User.findById(id, function (err, user) {   user.remove(function (err) {}); });

JSON/REST API

 app.post('/books', function (req, res, next) {   var book = new Book(req.body);   book.save(function (err, book) {     if (err) return next(new Error('Server error'));     res.send(200, {book: book});   }); }); app.get('/books/:id', function (req, res, next) {   Book.findById(req.params.id, function (err, book) {     if (err) return next(new Error('Server error'));     if (!book) return res.send(404, {error: 'Not found'});     res.send(200, {book: book});   }); }); // ...

Real-Time


socket.io


 var io = require('socket.io').listen(80); io.sockets.on('connection', function (socket) {   socket.on('my event', function (data) {});   socket.emit('another event', data); });

Demo Time

What else?

  • Forever
  • Nodemon
  • Node-Inspect
  • Meteor
  • JXcore
  • CLI
  • Front-end tools

Links


Node.js :: Introduction — Part 2

By Roman Liutikov

Node.js :: Introduction — Part 2

Introduction to Node.js development. A brief talk about Node's API, frameworks & libs, use cases and prototyping.

  • 2,774