Skip to content

Latest commit

 

History

History
148 lines (104 loc) · 5.19 KB

backend.md

File metadata and controls

148 lines (104 loc) · 5.19 KB

Index

Backend

Node.js

  • JavaScript on the server
  • Strictly speaking, Node is a runtime: a set of low-level routines written in C++ based around Chrome's V8 engine
    • V8 is a compiler, not an interpreter: implications for speed and resource consumption
  • Unlike browser-based JavaScript, Node has access to server resources including files on disk, networking, and other features of the operating system
  • Node's package manager, npm, has become incredibly popular
  • Dates back to 2009, with meteoric rise in popularity since then

Non-blocking I/O

  • Part of Node's appeal is its ability to execute asynchronous code
  • Node operates on a single thread, but all functions which perform input/output operate from a separate pool of threads managed by libuv
    • Node waits for a callback but can do other things while it waits. This behaviour is said to be event-driven (sometimes called the event loop).
  • Design allows thousands of concurrent requests
  • Can't make use of multi-core processors without explicitly handling child processes (for example, using the cluster module)

require vs import

  • Node's module system came from CommonJS. You may encounter a lot of code that looks like this:

    var http = require('http');
    var foo = require('foo');
  • It's certainly possible to use ES6 imports:

    import http from 'http';
    import path from 'path';
  • Because these features are fairly new to the language, it's necessary to use a transpiler to translate the ES6 features of the language into something that can be readily understood by Node. As the toolset matures, this should gradually become unnecessary.

    var gulp = require('gulp');
    var babel = require('gulp-babel');
    
    gulp.task('default', function() {
        return gulp.src('server.js')
            .pipe(babel())
            .pipe(gulp.dest('dist'));
    });
    • Here we use Babel to process the server file, then output to the dist directory

Further Reading

Express

  • Express is a minimalist web framework that sits on top of Node.

  • Has features for defining models, serving static content, and exposing APIs

  • For example, a minimal HTTP server can be written like so:

    import http from 'http';
    import path from 'path';
    import express from 'express';
    
    let router = express();
    let server = http.createServer(router);
    
    router.use(express.static(path.resolve(__dirname, '../client')));
    
    server.listen(process.env.PORT || 3000, process.env.IP || "0.0.0.0", function(){
      console.log("Ok");
    });
    • This serves everything in the client directory as static content
    • The port to listen on is held in the environment variable $PORT

Everything is 'middleware'

  • In Express, almost every part of request handling is treated as middleware.
    • Flow of execution is passed from middleware to middleware using the next function.

      // app.js
      import authenticate from 'authenticate';
      import aardvarks from 'aardvarks';
      
      app.use('/aardvarks', authenticate);
      app.use('/aardvarks', aardvarks);
      
      
      // authenticate.js
      app.all('/aardvarks', function (req, res, next) {
        checkUserAuth().then(function (user) {
          if (user.isAuthenticated()) {
            req.user = user;
            next();
          }
          res.status(401).json({ message: 'Please login to access this resource.' });
        });
      });
      
      
      // aardvarks.js
      app.get('/aardvarks', function (req, res, next) {
        let aardvark = new Aardvark();
        res.json(aardvark);
      });
    • This provides security because the order of execution is guaranteed: the authenticate middleware will always execute before aardvarks

      • If the user fails authentication, a response is written with HTTP status code 401
    • Notice that before the call to next, the request object is modified directly with new information (the user object)

      • Careful: it's possible to accidentally overwrite properties on the request
    • Middleware can be built up in this fashion into a middleware stack

Feathers

  • Feathers is an Express wrapper that takes care of boilerplate tasks

  • Makes setting up a REST API fairly trivial:

    import feathers from 'feathers';
    import bodyParser from 'body-parser';
    import mongoService from 'feathers-mongo';
    
    let app = feathers()
      .configure(feathers.rest());
      .use(bodyParser.json())
      .use('aardvarks', new mongoService('aardvarks'));
    
    let port = 8080;
    app.listen(port, function () {
      console.log(`Listening for Orycteropus afer on port ${port}...`);
    });

Index