SPA Development
for the
Server-Side Developer

By Abram Adams

@Abram_Adams

aadams@cfxchange.com

https://github.com/abramadams

http://cfml-slack.herokuapp.com/

Who Am I?

Overview

  • Define what a SPA is (and when to build one)
  • Contrast traditional server-side vs client side concerns
    • Session/State management
    • Security - Client side vs server side security
    • Downloading files
    • Delivering static assets
    • Development environments/Deployment
    • SEO

What this talk is NOT

  • Deep dive into a particular SPA framework
  • Complete guide to building SPAs - we just cover specific areas that I've had gotchas

What is a SPA?

"...a web application or web site that fits on a single web page with the goal of providing a more fluid user experience akin to a desktop application" -  Wikipedia

This is in contrast to traditional web apps that rely on the Request/Response paradigm in which every page is requested from the server.

Should I SPA?

When Should I?

  • Boss/Client says you have to
  • Building application vs content site
  • Building desktop applications (i.e. via Electron)
  • Building offline-first applications
  • JS heavy websites that share common functionality across much of the site
  • Real-time persistence
  • Long-lived user interaction
The Old Way

Request/Response

The SPA Way

SPA Request/Response (Request 1)

SPA Request/Response (Request ++)
RESTFul API

WTF?

What is a RESTFul API?

“REST,   or REpresentational State Transfer,   is   a   method   for computer  programs  to  talk  to  each  other  over  networks.” -- Adam Tuttle, REST Assured: A Pragmatic Approach to API Design

“It  is  a  set  of generalized conventions that make it easier for API-client developers to understand how to manage data over network protocols —like HTTP— with very little additional context and documentation”  -- Adam Tuttle, REST Assured: A Pragmatic Approach to API Design

State

  • Shopping Cart Contents
  • User Profile
  • Stored Actions
  • Form State
  • etc...

Request/Response

HTTP:/1.1 200 OK
Set-Cookie: cfid=1803
Set-Cookie: cftoken=c95c2c0f0e62813d-39..
        

SPA Request/Response (Request ++)

So, how do we manage state?

Client-Side

  • Memory (JavaScript variables)
    • $rootScope, $scope, etc...
    • window.myGlobalVar, etc...
    • this.state.myVar, etc...
  • LocalStorage
  • SessionStorage
  • IndexDB
  • SQLite, etc...
  • Cookies (though why?)

So... no server state?

Server-Side

  • NOT IN SESSION SCOPE!!!
    • Every request is a new "session", disable SessionManagement!
  • Authentication/Authorization must happen every request
    • Be careful to make sure this is fast!
  • Every request must not rely on previous request(s)
    • XHR calls can/will happen in random order!

Authentication

&&

Authorization

  • Each Request is a New Session
  • Cookies aren't passed on XHR requests
  • Authentication Must Happen Each Request
  • Authorization Must Happen Each Request

Authentication

"Authentication is the process of verifying who you are. When you log on to an PC with a user name and password you are authenticating." - ServerFault

"Authorization is the process of verifying that you have access to something. Gaining access to a resource (e.g. directory on a hard disk) because the permissions configured on it allow you access is authorization."  - ServerFault

Authorization

Types of Authentication

  • Basic Authentication
    Username/Password sent on every request
    • OK if over SSL
    • Cannot invalidate session without changing password
    • Cannot restrict/permit multiple devices
  • Token-Based Authentication
    Username/Password sent on initial request, authorization token set on subsequent requests
    • More secure (tokens change often and are difficult to guess)
    • Full control over session
    • Full control over devices/multiple logins

Demo!

Demo!

Downloading Files

This used to be so easy

<cfheader name=“Content-disposition” value=“attachment;filename=#dafile#”>
<cfcontent file=“#dafile#” type=“application/pdf”>
function download(filename, text) {
    var element = document.createElement('a');
    element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(text));
    element.setAttribute('download', filename);

    element.style.display = 'none';
    document.body.appendChild(element);

    element.click();

    document.body.removeChild(element);
}

// Start file download.
document.getElementById("dwn-btn").addEventListener("click", function(){
    // Generate download of hello.txt file with some content
    var text = document.getElementById("text-val").value;
    var filename = "hello.txt";
    
    download(filename, text);
}, false);
<a href="/assets/cf.pdf" download target="_self">
    Download cf.Objective() Schedule
</a>

OR

<a href="http://myrestendpoint.com/download?filename=server.pdf" 
    download="server.pdf" 
    target="_self">
    Download Server Details
</a>
// download photo using FileSaver.js
// https://github.com/eligrey/FileSaver.js/
photoService.downloadPhoto( formData ).then( function( data ) {
    var blob = new Blob( [ data.data ], { 'type': "image/jpeg" } );
    saveAs( blob, formData.fileName + '.jpg' );
} );

Static Assets

Your App is now a static asset

Development Environment

  • Local Node.js server
  • Gulp/Grunt/Webpack + Live Reload, BrowserSync, etc...
  • Sublime, VS Code, Atom + Some Shell/Terminal
  • App should have Prod/Dev environment variables (i.e. api urls, etc...)

Deployment

Deployment Considerations

  • SERVER LAND: you change the code, deploy and your users instantly get the changes

 

  • SPA LAND: your changes can get pushed, but the browser may decide not to download it.  YOU HAVE TO EMPLOY A CACHE BUSTING STRATEGY

Deployment Considerations

  • SERVER LAND: scaling horizontally meant duplicating complex server environments

 

  • SPA LAND: easily deploy to many different servers or CDNs without the need for complex/expensive servers

Deployment Considerations

  • SERVER LAND: frequent deployments can be snuck in without user noticing

 

  • SPA LAND: every deploy requires a full app download/reload (unless using hot module or other lazy loading)

SEO

It doesn't just happen

  • Meta data
    • Descriptions
    • Titles
    • Keywords
    • Images, etc..
  • Indexing

https://prerender.io/

The End

@Abram_Adams

aadams@cfxchange.com

https://github.com/abramadams

http://cfml-slack.herokuapp.com/

SPA Development for the Server-Side Developer

By Abram Adams

SPA Development for the Server-Side Developer

  • 714