First, if you only render HTML from the server, why do you need a JS framework? Just serve the full page and cache it.
Exactly, you don’t need a JavaScript framework all the time. The problem with JS frameworks is that you don’t have control of the code and therefore can’t fix problems that arise from them (see Angular 2-way binding).
Frameworks are only useful for developers that don’t have enough experience to understand how the web platform works. The problem is when the company brings experienced developers later in the game, then they can’t make the expected progress.
They have to spend the time to fix a lot of bad code laying around. Things get worse when everything is tied to a framework you can’t change any more or an old version you can’t upgrade.
Returning HTML from the server prevents you from having to write additional code for caching, you just need to understand how HTTP works.
Secondly, unlike with JSON data structure, HTML is pretty hard to traverse.
You don’t need to waste your time to write code to traverse HTML, the browser already does this for you. The DOM API has evolved wonders, you have document.querySelectorAll
where you can find any element you want without even having to include jQuery.
The reason you traverse JSON is just to recreate HTML anyway. Wy complaining about a problem you created yourself?
And you can’t really build a rich UI from snippets of HTML
You can create rich UIs from HTML, after all, that’s what you create with JavaScript. Try to send a JSON to the browser and see how it looks like: just a bunch of text.
In order to create a rich UI you need to have a JavaScript client for it, the browser doesn’t understand it to render something useful and that’s why it shows a pile of text in the screen.
You can return static HTML and then progressively enhance it with JavaScript. JavaScript is part of the HTML format, it’s called code on demand.
Just remember that the JavaScript code and the server that returns the HTML have to live on the same deployment pipeline, otherwise, you’ll have to make 2 deployments to deliver a single feature. See here for an example and details.
Lastly, if you have more than one client responding with HTML is wasteful and probably unnecessary.
Which another client? Mobile? You don’t need to even write a client for that.
HTTP has something called Content Negotiation. Different clients will request different Content-Types for a given resource. Browsers may request text/html
, Jasonette may request something else, external clients may request another type.
What you need to worry about for external clients, like third parties, is the hypermedia format. Make sure that the format of the response you’re sending abides by a format that can afford a client to code against it. Don’t send domain-specific information bound to the message. If you do that, it will be impossible to change it without breaking code that is using it and you’ll start to version stuff like /v2
, /v3
, etc. Versioning of URLs is a middle finger to your API consumers.
I haven’t written specifically about this yet, but I will later.
A lot of stuff is already built in into the communication protocol, you don’t need to reinvent the wheel and recreate the HTML you already have or write application-specific code for mobile.
I really can’t imagine a scenario where you need to return a button element from an API
You can, it’s called a website, but you’re not the one who codes against it, the browser does. The server returns a <button>
and the browser codes against that API.
Just because you can’t see it, that doesn’t mean it’s not there.
By the way, the only reason people return JSON from the server in the context of web pages is to re-create HTML anyway. I can’t imagine a reasonable scenario where you would have to return JSON from the server, write a lot of code and then end up with the same thing you could have returned from the first place: HTML. Yet, most of the developers do it out of cargo cult programming.
You know what I believe happened?
“Front-End” developers (myself included btw) started programming in the browser with JavaScript. Unfortunately, they didn’t understand how the communication protocols between client and server worked beside simple text transfer, so they started returning structured JSON from the server to build everything client-side. They also rediscovered simple patterns of communication like RPC, they’re really easy to rediscover.
If you create specializations, you start to reinvent things. What happened here is that due to the lack of server-side coding skills, Front-End devs started to rebuild all the application logic in the browser and use an RPC style communication between JavaScript code and the server returning JSON. That’s why you see companies with “Front-End” and “Back-end” teams and a lot of problems because of that.
I’ll also elaborate this in detail at a given time.
I’d say this is actually an example of premature optimization. Solving a performance problem, which doesn’t exist.
There seems to be a misunderstanding of what Donald Knuth meant by “premature optimization”. In this case, he said that writing code to optimize your system when you don’t need to right now is considered premature optimization. However, not writing code to optimize your system when you don’t need to right now is not premature optimization.
You’re not writing any code!
That’s exactly what you have with the default HTTP cache mechanism. You get it for free without having to worry about writing code for it. If you do, then you have a stable architecture to build upon without having to rewrite your whole system.
You can even cache incrementally. Start with the default caching mechanism browser give to you for free, and then improve it. Even express JS has a default caching mechanism that watches for file changes and modifies the response accordingly to return either 200 or 304 statuses.
Premature optimization is to return JSON from the server, write a shitload of JavaScript code to create HTML in order to create “rich” applications that “feel” like native and have “native-like” performance. There you’re spending a lot of time to prematurely optimize for “native-like” performance.
That’s premature optimization and with drawbacks!
If you return HTML, you can incrementally evolve your application to improve perceived performance with JavaScript with less code/effort/cost. However, if you start with JavaScript and reinvent the browser, then you have a lot of effort/code/cost because you’re trying to prematurely optimize for “native-like” performance.
Start simple. Less code, fewer frameworks (which is also code, only you don’t have control of it). Then later, improve it.
Not the other way around.