- Server load is lessened because the browser is loading only static files
- The front-end developers don’t have to run a back-end server locally
- Front-end developers won’t mess up any of the back-end developer’s code
- The front and back ends are totally separate so they can be worked on independently by different teams and deployed separately
- The front-end and back-end team communication may stop or break down
- You’ll inevitably wrestle with browser inconsistencies and legacy browser support
The best way to handle this is to rethink your entire application architecture. Does having a pure RESTful API backend with a completely separate single page app on the front-end really make sense? No! It doesn’t unless you either really have your heart set on that sort of architecture with no regard for reality or you have an actual valid reason for structuring your app this way. Let’s assume neither of these apply to you because they shouldn’t in most cases.
If you want to secure sensitive information like API keys in a client-side application this is the way to do it.
Step 0: Overview of app architecture
We assume the use of any MVC framework on the back-end. It doesn’t matter if you use Rails, Sinatra, Express, Django, or anything else. As long as you use some framework that has routing handled by a controller using models to communicate with a database which is all rendered by a view template you’re in good shape. Don’t get suckered in by the idea that having a separate RESTful API that populates all the different UI’s on each of your supported devices is the way to go. Sometimes it works but as developers we need to think and choose the best tool for the task at hand. MVC isn’t sexy but it fucking works and with a little creativity we can create hybrid MVC/SPA web apps.
Step 1: Implement Hybrid View Rendering
If you’re lucky enough to be using a library like React then you get the added benefit of being able to use the same view code on both the client and the server. The idea here is that you pre-render a static version of your UI through your web framework’s views then React kicks in and makes it interactive. The benefit here is that the app loads instantly and the interactive portions of the UI are then loaded up when the DOM is fully loaded.
At this point you’ll want to have sessions handled on your back-end to identify users as well as CSRF tokens enabled. Your log in page can be a SPA that handles authentication but once a user is authenticated you implement a full page reload to move the user into the “protected” area of your application. During this full page reload you set up a session on the back-end.
When you load up your dashboard page or whichever page is the first page you see when logging in, you render the basic HTML for your view on the server side along with a hidden field for your CSRF token. This page will then be used as a single page app. In an SPA model each request makes an AJAX call to your backend and the page is updated in real-time on the client. This is accomplished by making sure you grab the value of the CSRF token input and sending it in your AJAX call. AJAX calls by default will send cookies so your pages are secured by ensuring the request comes from a user with a valid session and correct CSRF token.
Step 2: Routing and Controllers
In an Express app the lines between controllers and routes are sort of blurred but this advice still applies. You should split up your routes/controllers into sections. For example, if I were running an online note taking application I would have two sections. One for listing and choosing notebook, and creating notebooks then another section for the actual editor interface. There’d be 3 page reloads:
- One from the login/signup page to the dashboard (note/notebook listing page)
- One from the note/notebook listing page to the editor page
- One from the editor page back to the note/notebook listing page again
On each of these pages your back-end renders the view and then a JS framework takes over the rest of the interactions with the app.
Step 3: The API
I usually set up my API on a subdomain or in a versioned API path on the main domain like
mydomain.com/api/v1/endpoint/. With this sort of setup I recommend you render your views using a hybrid SPA/tranditional server rendering method then create a separate versioned API for your iOS app and third party integrations (if you support them).
This allows you the most flexibility with your front-end while making your life easy by getting around browser limitations and security issues like session handling and CSRF tokens. Meanwhile the rest of your non-web applications can use a pure RESTful API that responds with JSON.
Step 4: Securing API keys
As for any functionality in your application that requires you to communicate with a third party API you don’t control, the answer is to make a simple CSRF secured AJAX call to your own back-end and then let your server-side application make the API call on behalf of your front-end then return the response back to your client-side app.
In this way your API credentials are secured. Your keys can’t be leaked unless you somehow return them back to your front-end or someone hacks into your server and somehow gets a hold of your configuration files or environment variables.
So far this seems simple, obvious, and not much unlike the traditional way of doing things. That’s okay! There are a ton of great new ideas and techniques out there and SPAs with RESTful back-ends are all the rage – they’re super cool and have their place. You should definitely play with them and learn how to work with them but when it comes time to build a production ready application, you need to be realistic and decide whether all the shiny new toys are really all they’re cracked up to be or whether a little bit of old and new is the best solution for you.