Advertisement
Advertisement

More Related Content

Advertisement
Advertisement

Node Architecture and Getting Started with Express

  1. NODE.JS ARCHITECTURE AND GETTING STARTED WITH EXPRESS.JS Jordan Kasper | Developer Evangelist
  2. NODE.JS ARCHITECTURE
  3. MODULARITY
  4. MODULE PATTERNS There are various patterns... Simple Object API Revealing Module (Function Initialization) Object Constructor
  5. SIMPLE OBJECT API // lib/employee.js module.exports = {     salary: 50000,     giveRaise: function( amount ) {         salary += amount;     } }; Why not always use simple objects? Modules are cached!
  6. REVEALING MODULE PATTERN module.exports = function createWorker( options ) {     // Setup...     return {         salary: 50000,         giveRaise: function( amount ) {             this.salary += amount;         }     }; };
  7. OBJECT CONSTRUCTOR PATTERN var Worker = module.exports = function Worker( options ) {     // ... }; Worker.prototype.salary = 50000; Worker.prototype.giveRaise = function( amount ) {     this.salary += amount; };
  8. SCALING
  9. VERTICAL SCALING
  10. NODE CLUSTERING
  11. var http = require('http'),     cluster = require('cluster'); if (cluster.isMaster) {     for (var i = 0; i < numCPUCores; i++) {         cluster.fork();     }; } else {     http         .createServer(function(req, res) {             // ...         })         .listen(8080, ...); });
  12. USING A PROCESS MANAGER Easy clustering and scaling without altering application code StrongLoop Process Manager (strong-pm) PM2 Comparison Chart Forever
  13. LOAD BALANCING cluster uses a simple round-robin approach... ...but there are better ways!
  14. HORIZONTAL SCALING
  15. HORIZONTAL SCALING
  16. Nginx
  17. BASIC NGINX CONFIG server {     listen 80     location / {         proxy_pass http://localhost:3000;     }     location /static/ {         root /var/www/my­app/public;     } } $ sudo service nginx start
  18. NGINX LOAD BALANCER http {     upstream myapp {         least_conn; # round­robin is the default...                     # Or use ip_hash; for "sticky" sessions...         server www1.my­app.com;         server www2.my­app.com;         server www3.my­app.com;     }     server {         listen 80         location / {             proxy_pass http://myapp;         }     } }
  19. STRONGLOOP AND NGINX If you're using strong-pm you can use the ! StrongLoop nginx controller ~$ npm install ­g strong­nginx­controller ~$ sl­nginx­ctl­install Install the Controller on the load balancing host...
  20. ...then manage the load balancing infrastructure from :StrongLoop Arc
  21. SCALING WITH STRONGLOOP ARC
  22. Nginx
  23. EXPRESS.JS
  24. EXPRESS.JS Fast, light, unopinionated framework for web applications.
  25. EXPRESS HELLO WORLD ~/my­app$ npm init ... ~/my­app$ npm install express ­­save
  26. EXPRESS HELLO WORLD // in app.js var express = require('express'); var myApp = express(); myApp.get('/', function handleRoot(req, res, next) {     res.send('Hello World!'); }); myApp.listen(8080); ~/my­app$ node app.js
  27. SCAFFOLDING AN EXPRESS APP
  28. SCAFFOLDING EXPRESS Install the CLI generator first... ~$ npm install ­g express­generator ~$ express my­app ... ~$ cd my­app ~/my­app$ npm install
  29. A SCAFFOLDED APP my­app/  |_ bin            # execution file (shell script)  |_ node_modules  |_ public         # images, css, fonts, etc  |_ routes         # Node.js routing code  |_ views          # server­side templates  |_ app.js  |_ package.json
  30. RUNNING A SCAFFOLDED APP ~/my­app$ npm start {   ...,   "scripts": {     "start": "node ./bin/www"   },   ...
  31. CONFIGURING EXPRESS
  32. CONFIGURING EXPRESS var app = express(); app.set('views', 'views'); app.set('view engine', 'jade'); app.set('port', process.env.PORT || 3000); app.set('foo', 'bar'); server.listen( app.get('port') );
  33. REQUEST ROUTING
  34. BASIC ROUTING var express = require('express'); var myApp = express(); myApp.get('/', function handleRoot(req, res, next) {     res.send('Hello World!'); }); myApp.listen( 3000 );
  35. POST ROUTING myApp.post('/user', function createUser(req, res, next) {     // Create the user record...     res.redirect('/my­account'); });
  36. POST ROUTING myApp.post('/user', function createUser(req, res, next) {     // Create the user record...     // Where do we get the data from?     res.redirect('/my­account'); });
  37. MIDDLEWARE
  38. MIDDLEWARE EXAMPLES var express = require('express'),     bodyParser = require('body­parser'); var app = express(); // app config... // Parse POST form data... app.use( bodyParser.urlencoded({ extended: false }) ); app.post('/user', function createUser() {     var user = {         username: req.body.username,         ...     };     ... });
  39. ORDER MATTERS! Middleware are executed in the order specified app.use( express.logger('dev') ); app.use( myAuthModule() ); app.use( bodyParser.json() ); app.use(bodyParser.urlencoded({ extended: false })); app.use(express.static(path.join(__dirname, 'public'))); // Routing middleware...
  40. MIDDLEWARE - WHEN DOES IT END? Middleware processing ends when next() is not called (or an error is generated) app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ extended: false })); app.get('/about', function aboutUs(req, res, next) {     res.send('We are StrongLoop!');     // no call to next() }); app.get('/user', ...);
  41. CUSTOM MIDDLEWARE app.use(function (req, res, next) {     // Do some work...     // Modify the req or res...     // execute the callback when done     next(); });
  42. CUSTOM MIDDLEWARE - ERRORS app.use(function (req, res, next) {     // do something...     if (thereWasAnError) {         var err = new Error(' ... ');         next( err );         return;     }     // No error, so we proceed...     next(); });
  43. HANDLING MIDDLEWARE ERRORS app.use(function(err, req, res, next) {     // Do whatever you need to...     if (err.code === 404) {         res.redirect('/error­404');     } else {         // Or you can keep processing this (or a new) Error         next(err);     } });
  44. HANDLING MIDDLEWARE ERRORS Always set up a "catchall" error handler!
  45. SERVER-SIDE TEMPLATING
  46. TEMPLATES Small blocks that we can plug data into at run-time //­ /views/index.jade doctype html html     head         title #{title}     body         section.main­body.clear             #{homepageText}
  47. TEMPLATING ENGINE ~/my­app$ npm install ­­save jade var app = express(); app.set('views', 'views'); app.set('view engine', 'jade');
  48. USING A TEMPLATE app.get('/' function handleRoot(req, res, next) {     res.render('index', {         title: 'StrongLoop ­ Home',         homepageText: 'We all love StrongLoop!'     }); });
  49. DON'T FORGET YOUR MODULARITY!
  50. NOT MODULAR... var express = require('express'),     bodyParser = require('body­parser'); var app = express(); // app config and other middleware... app.post('/user', function createUser() {     var user = {         username: req.body.username,         ...     };     db.create(user, function() {         res.render('user/my­account', { ... });     }); });
  51. THE 4.0 ROUTER INTERFACE // in routes/users.js var express = require('express'); var router = express.Router(); router.get('/', function(req, res, next) {   // Get a list of users...   res.render('user/list', { results: users }); }); router.get('/:id', function(req, res, next) {   // Get a single user...   res.render('user/my­account', { user: user }); }); router.post('/', function(req, res, next) {   // Create a user...   res.redirect('user/my­account', { user: user }); }); module.exports = router;
  52. THE 4.0 ROUTER INTERFACE // in app.js var express = require('express'),     ...; var app = express(); // app config and middleware... app.use('/users', require('./routes/users'));
  53. REQUEST OBJECT
  54. QUERY PARAMETERS app.get('/users', function (req, res, next) {     var limit = req.query.limit || 10,         users = [];     // Retrieve all users...     res.render('user/list', {         results: users,         nextIndex: 11     }); });
  55. URL PARAMETERS app.get('/users/:id', function (req, res, next) {     var id = req.params.id,         user = null;     // Retrieve a single user...     if (req.xhr) {         res.json({ user: user });     } else {         res.render('user/single', {             user: user         });     } });
  56. URL PARAMETERS app.get(/^/users/(d+)$/, function (req, res, next) {     var id = req.params[0],         user = null;     // Retrieve a single user...     // ... });
  57. RESPONSE OBJECT
  58. RESPONSE METHODS response.send(data) or response.end(data) response.status(httpStatus) response.send(201, someData) response.sendfile('path/to/someFile.json') response.download('/report-12345.pdf')
  59. HTTP STATUS CODES 2XX: for successfully processed requests 3XX: for redirections or cache information 4XX: for client-side errors 5XX: for server-side errors
  60. QUESTIONS? NODE.JS ARCHITECTURE AND GETTING STARTED WITH EXPRESS.JS Jordan Kasper | Developer Evangelist Join us for more events! strongloop.com/developers/events
Advertisement