Comparing JAMstack and Rails
Jon Sully
7 Minutes
Two different tools for two different jobs
One of my fellow Netlify Pilots, Aaron recently proposed this question in The Forums:
There is often talk of Statics sites and Dynamic sites. The difference seems simple but I feel with JAMStack, prerendering initial load with hydration etc, the lines become blurred?
I want to ask everyone, what canβt JAMStack do? In what situation would it not work? As far as I can tell Iβve made CRUD applications, data driven interactive applications too. With sites such as blogs it tends to be that most will rebuild when content changes, invalidate cache and immediately go live, but you can still pull data from apiβs and trigger CRUD actions on databases via apis.
Iβve found that I end up writing more apis like wrappers around other services and they are naturally more reusable.Is there anything I am missing that a truly dynamic site handles way better or something that JAMStack can simply just not achieve?
And ultimately, that’s a fantastic question. What are the ‘limits’ of JAMstack? What can’t JAMstack accomplish? This got me down a thought rabbit-hole and had me actively comparing JAMstack to Rails pretty deepy… although Rails is a specific framework and JAMstack is just a paradigm, still. Here’s what I wrote back:
tl;dr: JAMstack’s benefits shine most for web sites rather than web apps
“JAMstack” in it of itself isn’t actually a particular framework or language, just a paradigm primarily leveraging statically/build-time-generated Markup, Javascript (presumably just on the browser side… SSGs written in Go are still ‘JAMstacky’), and APIs for pulling in data (I think at its genesis, the “A” in JAMstack implied APIs for consumption client-side once the static markup had loaded in the browser, but I wonder now if it also includes APIs leveraged at build-time π€) β but the pivotal factor here is the static / build-time generated markup. It’s that static, plain-old-files HTML that can be easily distributed across the globe and served from any old web-server simultaneously across the planet (thanks Netlify!). The best UX and performance in JAMstack come from having as much static-markup as possible.
Contrast that with a web-app. (Yes I know this is a definition subject to much internet-scrutiny) A web-app is an application β something you interact with heavily in both directions. You issue commands to the application and it does things, it gives you feedback and tells you information. This is all very vague but the key signature that differentiates a web site from a web app is the level of two-way interactivity that occurs.
Netlify itself actually hosts a great example of this contrast. Go look at Netlify.com (the public marketing website) β click around on some pages and read some stuff.. then click around to other pages and read more stuff π pretty much everything on Netlify.com is textual/image content made to be consumed by you and me. That’s one-way interactivity. They write stuff on the site and we read it. Is there a way to ‘interact’ with the site? Sorta β this page https://www.netlify.com/enterprise/contact/ has a nice contact form that allows you to interact with the site in the other direction (us sending data back to Netlify) but that’s about it for Netlify.com (and, for what it’s worth, that form is actually a Hubspot embedded form.. so not really “part of the site” anyway).
Now instead go to app.netlify.com β the admin interface for all of your Netlify sites. There’s data there for you to see; tons of it! Each site’s build status, your bandwidth usage, build minutes used, domain setup, etc. etc., basically all of the features of Netlify. So that covers the “one-way” interactivity in the sense that Netlify is telling us data. But look how much interactivity there is in the other direction: I can add new sites, kick off builds, control site settings, heck I can log in β there’s a whole user system in place and all the content is customized per user (I can’t see your sites! π), etc. The premise I’m making here is that there’s a ton of interactivity in both directions. app.netlify.com (aptly named) is a web-app. Not a web-site. In this particular case, it’s an app for managing our Netlify sites, but nonetheless, an app.
SO, I say all of that to say my hot take: the benefits of a JAMstack site are maximized by web-sites but shrink quite a bit when using JAMstack to build web-apps. But why? Because of static rendering. When we think about all of the two-way interactivity involved in a web-app, almost always that involves user-specific content. It’s the reason I can’t see your sites when I log into app.netlify.com and you can’t see mine, even if you tried to go to https://app.netlify.com/teams/jon-sully/
. The content that ultimately renders in my view is different than yours: the number of sites I have and their names, the settings for each of them, my team’s name, the domains I use β literally all of the interactivity sections (in either direction) that I described earlier will be different between the two of us. That means that none of that content can be rendered statically at build-time β anything rendered statically at build time will be available just the same to everyone. In the case of app.netlify.com the static content β the HTML rendered at build time β is mostly just the basic design layout and header text. Everyone’s going to see this same box shape with these same h2
buttons and links:
But if you think about it, that’s not actually the majority of the content on the page β that’s not what we came to the app for. We came to the app for all the interactive stuff. The data we read about our sites and the functional knobs and buttons that we can use to administrate our sites. So even though this ‘shell’ is statically rendered at build time, using JAMstack for a web-app can potentially lead to two-step experiences for users since the majority of the content on the screen for a web-app tends to need to come from a server that can render the user-specific content anyway. In this case we load app.netlify.com and the design shell gets pulled down (you might notice the spinning Netlify icon), but once all the javascript loads and runs in the browser, then subsequent requests need to be made to the Netlify API to actually retrieve all of the content for your specific user to hydrate the design template. With web-apps where most of the content on screen needs to be per-user, this tends to be a longer request cycle than more traditional systems that just render the content in a template server-side and send back the formatted and filled-out HTML.
On the other hand, using JAMstack for web-sites is unbeatable. Traditional server-based frameworks can leverage caching tools and mechanisms to achieve close-to-JAMstack-level results but not without a lot more complexity and knowledge. If your site is mostly statically-rendered (build-time) content, then packing that down to plain HTML files and distributing them across a global CDN is hard to beat. There’s just no denying it. Things that can be rendered at build-time should be.
Different projects just have different needs.
And, before closing out, I should mention that there are a ton of shades of grey here too. Is an eCommerce site a web-site or a web-app? I’ll let you decide π but the point is that many web-sites can be better off with JAMstack over a traditional server-render approach even if they have some per-user pieces of content / components (e.g. all of your products can be build-time rendered but your shopping cart and order history better be per-user). The balance lies in how much of your project’s content is static vs. user-driven. Understanding that balance will lead you to the right tool for the job. π―
I’m also not going to get into the sort-of-server-rendered approach using serverless functions instead of an actual server framework β more shades of gray there. Looking at you, NextJS!
Hope that provides some insight!
–
Jon
There you have it!
When figuring out the right tool for the project just remember, the two primary factors are how much of the content is static (not changing per-user) and the required latency between the content updating and becoming available publicly.
Oh! And if you ever wonder how fast the server-side approach can be with just a few good caching policies, head over to Dev.to. Ignoring the article contents, just experience how fast the whole site runs. It’s Rails π