Powerful Backend & API Solutions for Single-Page Applications

Matias Niemelä (@yearofmoo)
http://www.yearofmoo.com

About Me

Fullstack developer from Toronto

Core developer on Angular

BSc in Computer Science

Born in Helsinki, Finland

JavaScript, Dart, Ruby and Clojure

http://www.yearofmoo.com

Slides + Code

http://yom.nu/fitc-web-unleashed

http://yom.nu/fitc-web-unleashed-code

What am I going over today?

What exactly is a SPA?

The role of the API

Popular backend technologies

Crazy 3rd Party Tools

What is a SPA?

New web app paradigm

dynamic client-side websites

The only delivers data

No more full page refreshes!

So what really is a SPA?

Let's see something in action then...

Remember XML + XSLT?

You craft your data using XML

XSLT turns that XML into HTML

The webpage renders

Data is separate from HTML

The role of the backend for a SPA

Acts as a database transport layer

No more templates are delivered--only data

Easier to cache, scale & secure

Less data == less bandwidth

Does the backend matter anymore?

Yes of coarse it does, but...

The backend's job is to deliver data

Not to fully parse the HTML output for a page

So it's basically an API

But do popular frameworks craft good APIs?

Dynamic websites are oldschool

Dynamic websites can still render templates

PHP, Rails, Express all do it

But better to look for API generation tools

And leave the template processing up to the SPAs!

XML + XSLT


<numbers>
  <number>1</number>
  <number>2</number>
  <number>3</number>
  <number>4</number>
  <number>5</number>
  <number>6</number>
  <number>7</number>
  <number>8</number>
  <number>9</number>
</numbers>
    

XML + XSLT


<xsl:template match="/">
<html><body>
  ...
  <xsl:for-each select="numbers">
    <div>
      <xsl:value-of select="number"/>
    </div>
  </xsl:for-each>
  ...
</body></html>
</xsl:template>
    

Example 2: ng-tube.com

http://www.ng-tube.com

What's the big deal with it?

Uses a public API to do it's thing

The API code is completely separate

Backend Frameworks

Easily over 100 frameworks out there

We want an easy API generation tool

Let's explore some frameworks

Backend Frameworks: Ruby

Rails

Sinatra

Rails

Ruby is the main programming language

Great for building large web apps

Huge ecosystem of tools and plugins

Great testing mechanisms

Fast moving, configurable

Let's see the backend in action

Create a scaffold

Load up the website

Code


class BooksController < ApplicationController
  before_action :set_book, only: [:show, :edit, :update, :destroy]

  def index
    @books = Book.all
  end

  def show
  end

  def load_book
    @book = Book.find(params[:id])
  end
end
    

jBuilder

Works great for building a complex API

API template code can be reused

jBuilder Code


# views/api/books/index.json.jbuilder
json.books = @books

# views/api/books/show.json.jbuilder
json.book = @book
    

rails-api

A smaller subset of features for Rails

But designed for API building

Better suited for something like AngularJS / Ember

Sinatra

Smaller applications, less code involved

Less conventional, more to the point

Sinatra Code


require 'sinatra'
require 'json/ext'
require 'sqlite3'

get '/api/books' do
  content_type :json
  rows = []
  $db.execute( "select * from books" ) do |row|
    rows.push(row)
  end
  rows.to_json
end

get '/api/books/:id' do
  id = params[:id]
  # ...
end
    

Backend Frameworks: JavaScript

Express

Sails

Other mentions

Express

Features

Simple, basic, barebones backend framework

Lightweight, easy to use

Runs on NodeJS

Organize the code yourself


var app = express();
var db = new sqlite3.Database("db.sqlite3");

var routes = require('./bookRoutes')(db);
app.get('/api/books', routes.index);
app.post('/api/books', routes.create);
app.get('/api/books/:book_id', routes.show);
app.put('/api/books/:book_id', routes.update);
app.delete('/api/books/:book_id', routes.destroy);

app.param('book_id', routes.findBook);

db.serialize(function() {
  express.listen(8888);
});
    

module.exports = function(db) {
  return {
    index : function(req, res) {
      var rows = [];
      db.each("SELECT * FROM books", function(err, row) {
        rows.push(row);
      }, function() {
        res.json(rows);
      });
    },

    show : function(req, res) {
      res.json(req.book);
    }
  };
};
    

The Express Ecosystem

Progressive community

Lots of plugins

Sails.js

Rails-like framework for building node backends

Scaffolding, searching capabilities, TTD-oriented

Rich ORM and data mapping capabilities


module.exports = {
  adapter: 'sails-sqlite3',
  
  attributes: {
    title: { type: 'string', required: true },
    description: { type: 'text', required: true },
    isbn: { type: 'string', required: true }
  }
};
    

// controllers/BookController.js
module.exports = {
  index: function(req, res) {
    Book.find(function(err, books) {
      res.json({ books: books });
    });
  },
  create: function(req, res) { ... }
};
    

// config / routes.js
module.exports.routes = {
  'get /users.json': {
    controller    : 'Book',
    action        : 'index'
  },
  'post /books.json': {
    controller    : 'Book',
    action        : 'create'
  }
  //...
};
    

Other Mentions: Hapi

Other Mentions: Synthjs

Backend Frameworks: PHP

Slim

Raw PHP

Slim

Nice router code for making an API

http://www.slimframework.com


<?php
  require 'Slim/Slim.php';
  $app = new Slim();

  $app->get('/api/books', 'getBooks');
  $app->get('/api/books/:id',	'getBook');
  $app->post('/api/books', 'addBook');
  $app->put('/api/books/:id', 'updateBook');
  $app->delete('/api/books/:id', 'deleteBook');
  $app->run();
?>
    

<?php
  function getBooks() {
    $sql = "select * FROM books";
    $query = $db->query($sql);  
    $books = $query->fetchAll(PDO::FETCH_OBJ);
    echo json_encode($books);
  }

  function getBook() {}
?>
    

Raw PHP

Effectively Slim minus the routing

Tricky to route without Apache/NGINX

Worth using a framework to do so

Other mentions: Lavarel

http://laravel.com/

Backend Frameworks: 3rd Party

Firebase

Backendless

Built.io

Mashape

Firebase

Firebase is a realtime Backend As a Service

Use the same backend for AJAX + realtime

https://www.firebase.com

Firebase

Change the URL routing and go from there


.constant('API', 'https://booksapi.firebaseio.com/')
    

Backendless

A bigger backend ecosystem

Uses its own library code

Comes packed with lots of features

http://backendless.com/

Backendless


self.submit = function(data) {
  var db = Backendless.Persistence.of(Book);
  var instance = new Book(data);
  instance.save(instance);

  function Book(data) {
    this.title = data.title;
    this.description = data.description;
    this.isbn = data.isbn;
  }
};
    

Built.io

Another BaaS System

Also uses its own library code

https://www.built.io/


.controller('BooksCtrl', function() {
  var myQuery = new Built.Query('book');
  myQuery.exec({
    onSuccess: function(books) {
      self.entries = books;
    }
  });
});
    

.controller('BooksForm', function() {
  self.submit = function(data) {
    var Book = Built.Object.extend('book');
    book = new Book();
    book.set(data);
    book.save();
  };
});
    

Mashape

Large web wrapper for APIs

One single API point for everything

https://www.mashape.com/dashboard

Mashape

Mashape: ISBN API


var url = "https://community-isbndb.p.mashape.com/" +
  "books.xml?index1=isbn&value1=ISBN_VALUE";

unirest.get(url).header("X-Mashape-Key", "...KEY...")
                .end(function (bookMatches) {
                  //data ...
                });
    

Other Crazy Ideas

Zapier

Kimono Labs

Amazon Mechanical Turk

Zapier

Make your SPA use Zapier

Zapier can then communicate with other services

https://zapier.com/

Zapier

Amazon Mechanical Turk

Maybe we can hook into Mechanical Turk using JSON?

Think of something crazy stupid to automate

https://www.mturk.com/mturk/welcome

Kimono

Turn a website into an API

What about if we wanted to collect all books for ourselves?

https://www.kimonolabs.com/

Kimono

Thank you

It was a pleasure

Matias Niemelä
@yearofmoo