SPA Development
for the
Server-Side Developer

By Abram Adams


Who Am I?


  • 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


The SPA Way

SPA Request/Response (Request 1)

SPA Request/Response (Request ++)


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


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


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

SPA Request/Response (Request ++)

So, how do we manage state?


  • 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?


    • 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!




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


"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


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



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); = 'none';


// 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 href="" 
    Download Server Details
// download photo using FileSaver.js
photoService.downloadPhoto( formData ).then( function( data ) {
    var blob = new Blob( [ ], { '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 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)


It doesn't just happen

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

The End


SPA Development for the Server-Side Developer

By Abram Adams

SPA Development for the Server-Side Developer

  • 665