ME[A]N Stack

Let's just remove that A for now

MEN Stack; the stack with a stash

We will go over express.js, meteor, and feathers

But first let's learn what Node.js is

About

 

Node.js® is a JavaScript runtime built on Chrome's V8 JavaScript engine. Node.js uses an event-driven, non-blocking I/O model that makes it lightweight and efficient. Node.js' package ecosystem, npm, is the largest ecosystem of open source libraries in the world.

1

Blocking

 
const fs = require('fs');
fs.readFile('/file.md', (err, data) => {
  if (err) throw err;
  console.log(data);
});
fs.unlinkSync('/file.md');

Non-Blocking

 
const fs = require('fs');
fs.readFile('/file.md', (err, data) => {
  if (err) throw err;
  console.log(data);
  fs.unlink('/file.md', (err) => {
    if (err) throw err;
  });
})

Pure Node Example

 

As an asynchronous event-driven JavaScript runtime, Node is designed to build scalable network applications. In the following "hello world" example, many connections can be handled concurrently. Upon each connection the callback is fired, but if there is no work to be done Node is sleeping.

 
const http = require('http');

const hostname = '127.0.0.1';
const port = 3000;

const server = http.createServer((req, res) => {
  res.statusCode = 200;
  res.setHeader('Content-Type', 'text/plain');
  res.end('Hello World\n');
});

server.listen(port, hostname, () => {
  console.log(`Server running at http://${hostname}:${port}/`);
});

Express.js

  • Adds Structure
  • Easier APIs
  • Middleware

Let's look at an example

 

BTW, you need to have npm initialized and express installed

1
$ npm init

$ npm install express --save

Hello Express

 
var express = require('express');
var app = express();

app.get('/', function (req, res) {
  res.send('Hello World!');
});

app.listen(3000, function () {
  console.log('Example app listening on port 3000!');
});
$ node app.js

Start your server with

 

navigate to http://localhost:3000/ in a browser​

 

REST APIs

 
app.get('/', function (req, res) {
  res.send('Hello World!');
});

app.post('/', function (req, res) {
  res.send('Got a POST request');
});

app.put('/user', function (req, res) {
  res.send('Got a PUT request at /user');
});

app.delete('/user', function (req, res) {
  res.send('Got a DELETE request at /user');
});

Static Files (assets)

 
var express = require('express');
var app = express();

app.use(express.static('public'));  // Now, you can load the files that are in the public directory
// Example: http://localhost:3000/images/kitten.jpg

app.get('/', function (req, res) {
  res.send('Hello World!');
});

app.listen(3000, function () {
  console.log('Example app listening on port 3000!');
});

Feathers.js

 
  • minimalist real-time framework
  • Easier APIs
  • Built on Express.js

Getting Started

$ npm install -g feathers-cli

$ mkdir my-app

$ cd my-app

$ feathers generate

$ npm start

Feathers can make getting started easier, but it can also add some complexity 

Feathers REST Example

const feathers = require('feathers');
const rest = require('feathers-rest');

const app = feathers();

app.configure(rest())
  .use(function(req, res, next) {
    req.feathers.fromMiddleware = 'Hello world';
    next();
  });

app.use('/users/:userId/messages', {
  get(id, params) {
    console.log(params.query); // -> ?query
    console.log(params.provider); // -> 'rest'
    console.log(params.fromMiddleware); // -> 'Hello world'
    console.log(params.userId); // will be `1` for GET /users/1/messages

    return Promise.resolve({
      id,
      params,
      read: false,
      text: `Feathers is great!`,
      createdAt: new Date.getTime()
    });
  }
});

app.listen(3030);

We won't use Sockets just yet (realtime)

MongoDB in Feathers

const feathers = require('feathers');
const rest = require('feathers-rest');
const socketio = require('feathers-socketio');
const errors = require('feathers-errors');
const bodyParser = require('body-parser');
var MongoClient = require('mongodb').MongoClient;
const service = require('feathers-mongodb');

const app = feathers()
  .configure(socketio())
  .configure(rest())
  // Turn on JSON parser for REST services
  .use(bodyParser.json())
  // Turn on URL-encoded parser for REST services
  .use(bodyParser.urlencoded({extended: true}));

  // Connect to your MongoDB instance(s)
MongoClient.connect('mongodb://localhost:27017/feathers').then(function(db){
  // Connect to the db, create and register a Feathers service.
  app.use('/messages', service({
    Model: db.collection('messages'),
    paginate: {
      default: 2,
      max: 4
    }
  }));

  app.use(errors.handler());

  var server = app.listen(3030);
  server.on('listening', function() {
    console.log('Feathers Message MongoDB service running on 127.0.0.1:3030');
  });
})

Mongoose for Data models

const mongoose = require('mongoose');

const Schema = mongoose.Schema;
const MessageSchema = new Schema({
  text: {
    type: String,
    required: true
  },
  read: {
    type: Boolean,
    default: false
  }
});
const Model = mongoose.model('Message', MessageSchema);

module.exports = Model;

Meteor.js

  • Ship more with less code
  • Build apps for any device
  • Full-stack with blaze, angular or react
  • Built on Express.js

We will build an example app with meteor now

Go to http://goo.gl/McdivB

We will go step by step through this tutorial

The Tutorial shows us how to create a modified MEAN stack app.

There are a lot of different ways to build full web apps with JS

You will choose the tech you want to use with your project

This is a part of the design process

Stacks we will use in class

  • Firebase, Angular 2, TypScript (FAT)
  • Firebase, Ionic 2, TypeScript (FIT)
  • Meteor.js (modified MEAN) (MEAT)
  • Feathers * Stack (*EAN)
  • Possibly a few more surprise stacks

deck

By James Brinkerhoff