Server Side Templates vs REST API and Javascript Front-End
A better user experience is the main reason why I prefer using server side templates instead of just client side rendering.
I sometimes get asked why my Flask course uses templates rendered on the server side instead of being backed by a REST API that uses a popular Javascript front-end framework.
The short answer is, most web applications I build are document based and if I may be so bold as to say, I think most web apps fall into this category too. We’re building sites that present data in the form of “pages”.
These pages might have real-time elements to it such as notifications and chat, as opposed to video games or something that’s highly interactive like Google Maps or Google Documents but at the end of the day, we’re displaying pages.
# What Is a Document Based Application?
Document based apps are all about presenting fairly structured data on a page and fits well with the whole request / response cycle which is how websites were designed to work.
Whether or not these pages are interactive isn’t important. You can still have a document based application feel like it’s alive.
For example, on GitHub, if you keep an issue page open, you will be able to see new comments get added without doing a full page reload. So don’t think just because you have a document based application that’s rendered on the server you can’t sprinkle in real-time effects.
# Server Side Driven Apps vs. API / Heavy JS Front-End
The biggest wins to using server rendered templates for most web frameworks are performance, plus you don’t need to duplicate your work on both the server & client side.
Server Side Templates
For example, let’s say you had a form that allows users to enter in a movie
title and description. Chances are you’ll have a Movie
model in your app code
and its schema would be defined at the database level.
Yeah I know, a lot of MongoDB JS developers are like “HAHAH IDIOT! It’s not 2006 anymore, no one uses schemas!” but I bet you end up writing your own schemas at the application level for any real world apps because it makes life so much easier when developing your app.
At this point, your schema is defined and with most web frameworks now you would hook up form validators. With Flask that would likely be WTForms. This is where you can declare things like “the title field must be a string in between 1 and 128 characters”.
Next up you’d handle the view layer which in Flask land is composed of both the URL endpoint and the data you’re going to respond with. Since we’re dealing with server side rendered templates, you would respond with a Jinja template that compiles into HTML.
Pretty straight forward. You have 1 schema definition, 1 form validator, 1
URL endpoint definition (for GET
/ POST
) and some code to render the
response itself.
Everything works as expected and your code to handle specific logic is in 1 spot. If someone fills out the form correctly, they get redirected to the “happy” path and if it’s incorrect the HTML template handles adding error classes to the form fields that are invalid.
API Back-End With a Heavy JS Front-End
With most frameworks if you tried to implement the server side example above with an API and heavy JS front-end then you would end up writing a heck of a lot more code.
You would need to define your API routes on the server side, but then also create a different set of routes and views on the client side using some Javascript library such as React, Vue, Angular, Ember, jQuery or any one of the other hundred choices.
For example you might have this as your API endpoint route: POST /api/v1/movies
,
but on the client you need /movies/new
or whatever you happen to name it. The
cognitive load is much higher because that client side router is a totally
different animal than your back-end set up.
Then there’s validation. You can’t just validate things on the client, so you still need to set up server side validation, but now you need to wire up ajax calls in your JS to verify and respond with various messages based on the validation that happened on the back-end.
It’s not the end of the world but it’s annoying.
Then there’s always the case of whether or not you want your app to work without Javascript. Now you would need both server side and client side templates, and also deal with things like flash messages on both sides. That sounds like a nightmare to maintain.
Oh, but it gets worse because a single page app has to store state. Yikes, now you need to model your data on both the server and client side and need some type of state management solution to keep them in sync.
For example, you’d probably want to know whether or not a user is logged in or not on the client side, which means your client side needs to know what a user is and what properties define it as being logged in, etc..
Performance and SEO woes
Offloading a ton of work to the client is actually way worse for performance, especially on mobile devices. That’s why a lot of big sites are moving towards solutions that render their app on the server and then keep things updated on the client side.
The problem is they need to re-invent a lot of wheels and add operational complexity to your stack because you need to run these services on your server for them to work.
For example, that’s what the Next.js project aims to do with React. Even AirBnB wrote a service for rendering Javascript views on the server with their hypernova project.
Here’s why AirBnB wrote hypernova:
First and foremost, server-side rendering is a better user experience compared to just client-side rendering. The user gets the content faster, the webpage is more accessible when JS fails or is disabled, and search engines have an easier time indexing it.
Calling all Javascript wizards
Now, don’t get me wrong. If you love JS some of these issues are less lame because at least you can write JS on both the back-end and front-end, but you’re still writing some duplicate code and need to context switch between both sides of your app, so it’s not the holy grail.
You also need to battle with libraries and frameworks that are moving faster than the speed of light. I don’t want to have to spend my time drastically refactoring apps every few months because entire APIs and functionality of major libraries change.
As much as I love nerding out over technology, I want to ship and maintain real apps.
I’m cool (and often happy) with refactoring apps for major version upgrades once a year but every few months is too much. That’s too much of a time sink and if you skip a few upgrades and then try to upgrade it, you end up having to nearly rewrite your app from scratch because so many things changed.
# Conclusion
So that’s why I continue to use Flask and Rails with primarily server side rendered templates. I sprinkle in Javascript when necessary and for 99.99% of the apps I develop this works great.
Is it the best answer for everyone and everything? Definitely not.
If I were developing an app that happened to need a very complex and interactive UI and sprinkling in a bit of JS wasn’t going to cut it, then I would reach for something like React or Vue and develop JUST that component of the app like that.
What style of web apps do you prefer? Let me know below!