83

When I first started learning PHP (about 5 or 6 years ago) I learned about Ajax, and I went through "the phases":

  1. Your server returns HTML data and you put it inside a DOM's innerHTML
  2. You learn about data transfer formats such as XML (and say "oooh so THAT'S what it's used for) and then JSON.
  3. You return JSON and build your UI using vanilla JavaScript code
  4. You move to jQuery
  5. You learn about APIs, headers, HTTP status codes, REST, CORS and Bootstrap
  6. You learn SPA, and frontend frameworks (React, Vue.js, and AngularJS) and the JSON API standard.
  7. You receive some enterprise legacy code and upon inspecting it, find that they do what's described in step 1.

As I worked with this legacy codebase, I didn't even consider that it could return HTML (I mean, we're professionals now, right?), so I had a hard time looking for the JSON endpoint that was returning the data that the Ajax calls populate. It was not until I asked "the programmer" that he told me it was returning HTML and being appended directly to the DOM with innerHTML.

Of course, this was hard to accept. I started thinking of ways to refactor this into JSON endpoints, thinking about unit testing the endpoints and so on. However, this codebase has no tests. Not a single one. And it's over 200k lines. Of course one of my tasks includes proposing approaches for testing the whole thing, but at the moment we're not tackling that yet.

So I'm nowhere, in a corner, wondering: if we have no tests whatsoever, so we have no particular reason to create this JSON endpoint (since it's not "reusable": it literally returns data that only fits on that part of the application, but I think this was already implied since it... returns HTML data).

What exactly is wrong with doing this?

Peter Mortensen
  • 1,050
  • 2
  • 12
  • 14
Christopher Francisco
  • 2,392
  • 1
  • 12
  • 27
  • 2
    Related: http://softwareengineering.stackexchange.com/questions/207835/is-it-ok-to-return-html-from-a-json-api – Machado Mar 14 '17 at 14:25
  • 3
    Also related: http://stackoverflow.com/questions/1284381/why-is-it-a-bad-practice-to-return-generated-html-instead-of-json-or-is-it <- A very good answer in SO. – Machado Mar 14 '17 at 17:22
  • Its not that crazy, though sometimes for scaling one moves away from having a dynamic server deliver html templates, since that's something a static server can often do. – Mark Rogers Mar 14 '17 at 17:41
  • ^ If you're serving templates only, that's ok. If you're serving dynamic HTML, like Razor Views for example, then you cannot rely on a static server. – Machado Mar 14 '17 at 18:18
  • 1
    Note that JavaServer Faces (JSF), the official web application framework for Java Enterprise Edition, works just like that - on AJAX calls, it returns pre-generated chunks of HTML to render client-side. Now whether that is a good idea is another question... – sleske Mar 14 '17 at 18:53
  • 1
    Nothing, especially whenever the Request `Accept` Header asks specifically for HTML and not JSON. – zero298 Mar 14 '17 at 22:10
  • 77
    A server using HyperText Transfer Protocol returning HyperText?! The horror! – Andy Mar 14 '17 at 23:01
  • 3
    @Andy To be perfectly honest, it's actually Generic Message Transfer Protocol: nothing about it is specific to transfering hypertext, opposed to FTP, which talks a lot about things specific to files and directories. – Joker_vD Mar 15 '17 at 09:23
  • 1
    @Joker_vD, it has request/response messaging paradigm, a predefined set of operations, and is a text-protocol. Not completely generic. Different from, say, SSH. – Paul Draper Mar 15 '17 at 19:36
  • 4
    @Joker_vD I've never heard of a protocol called GMTP. While things have evolved and you can send other types of content over HTTP, it wasn't the original intent. My point is that just because you can send other content besides HyperText using HTTP, it seems silly to suggest that its not valid anymore to use it for its original purpose. – Andy Mar 15 '17 at 21:07
  • @Andy It does sound silly when put that way but, to be fair, HTML was not originally intended to represent anything but a static page. Dynamically processing and loading portions of the DOM after the initial content has already loaded is a different concern, no matter what protocol is used. I think that's why this question has merit. – BCDeWitt Mar 16 '17 at 17:58
  • 1
    @BDawg Sure, dynamically generating a page of HTML client side wasn't he intent originally of HTML, but that has little to do with HTTP itself. I do think the question has merit as well, but others have already answered sufficiently, so i left a somewhat tongue-in-cheek comment. If you look below, you'll see at least one person arguing to never return HTML from an API (which I find absurd). – Andy Mar 16 '17 at 22:46

12 Answers12

122

What's actually wrong with an endpoint returning HTML rather than JSON data?

Nothing, really. Each application has different requirements, and it may be that your application wasn't designed to be a SPA.

It may be that these beautiful frameworks that you cited (Angular, Vue, React, etc...) weren't available at development time, or weren't "approved" enterprisey thingies to be used in your organization.

I'm gonna tell you this: an endpoint that returns HTML reduces your dependency on JavaScript libraries and reduces the load on the user's browser since it won't need to interpret/execute JS code to create DOM objects - the HTML is already there, it's just a matter of parsing the elements and rendering them. Of course, this means we're talking about a reasonable amount of data. 10 megabytes of HTML data isn't reasonable.

But since there's nothing wrong with returning HTML, what you are losing by not using JSON/XML is basically the possibility of using your endpoint as an API. And here lies the biggest question: does it really need to be an API?

Related: Is it OK to return HTML from a JSON API?

Machado
  • 4,090
  • 3
  • 25
  • 37
  • 1
    I do see this as a multifaceted situation, where the main driving force is simply preference. There could be security, performance, and library concerns for either participant in the communication, almost equalizing the choices. One tip that stood out in my mind beside simple subjective preference to the user and current working environment of the time, is that the API can be re-used by other types of clients, keeping the complexity and coupling minimized, which implicitly leads to making the web view still operate by transforming the API data into HTML, probably client-side at this point. – Pysis Mar 14 '17 at 20:18
  • 4
    I'd take a step back before saying it's just "simply preference". There are some "big deal" decisions you have to make: Is it an API or not, do I have the proper libraries to work with this as JSON data on the client, which type of client will I support (browsers without Javascript, for example), what volume vs. CPU time I have available to use, which strategy my programmers will leverage better, etc. etc. etc. – Machado Mar 14 '17 at 20:36
  • 1
    You don't have to make a decision on whether it's an API or not. It's *always* an API. The only question is whether you pointlessly couple it to your current use case. – DeadMG Mar 14 '17 at 21:37
  • 7
    “it won't need to interpret JS code to create DOM objects - the DOM objects are already there, it's just a matter of rendering them” — well, the *HTML* is already there (once it’s arrived over the wire). The browser has to parse the HTML and make the DOM objects from it. – Paul D. Waite Mar 14 '17 at 23:33
  • 7
    There's zero reason that HTML can't act as an API. Zero. None. In fact, HAL+JSON and HAL+XML bear a striking resemblance to HTML. Here's an excellent talk about REST. Relevant part about returning HTML from an endpoint is near the end. https://youtu.be/pspy1H6A3FM Personally, I make all my endpoints return both json and HTML. If you're writing discoverable services, it makes it really easy to browse it in... *gasp*... a browser. – RubberDuck Mar 15 '17 at 10:36
  • 4
    Because it's a complete bitch to extract the data you actually care about to try to use it in any new way? – DeadMG Mar 15 '17 at 11:12
  • @Machado Meant to phrase it as it's mainly the primary factor for what drives people to use certain technology or techniques, no matter how 'correct' or efficient it is, then I exactly went on to list a couple of other reasons. Also, every time I mention API, I'm sure that can generally apply to any form of data. Maybe I should also say, the 'data' part of data-driven design, or rather, not having the final resulting UI code be simply outputted, as again I mentioned somewhat unnecessary coupling. – Pysis Mar 15 '17 at 14:24
  • @RubberDuck Entirely valid point, but it should be pointed out that there is a difference between HTML designed for _presentation_ (which I assume is what the OP is dealing with, but I could be wrong - and yes, of course, HTML should not be used for presentation in the first place) and HTML designed for describing easily parsed data. – Michael L. Mar 15 '17 at 16:23
  • @DeadMG Sometimes you don't care about extracting the data and using it in a new way, sometimes you just want to display it. – Andy Mar 15 '17 at 21:16
  • I take strong objection to your "nothing". The worst part is that you lose all control of permissions model. Whereas JSON is pure data, HTML can contain code, so you have to be able to trust the source of the HTML you inject into your page - not just to be non-malicious itself, but also to be secure against having had malicious content injected into it. This is the equivalent of `fopen` vs `dlopen` in C. – R.. GitHub STOP HELPING ICE Mar 15 '17 at 23:15
  • "10 megabytes of HTML data isn't reasonable" — citation needed. I'd wager, that 10 Mb of HTML are *always* more reasonable than 5Mb of Javascript, used to generate 10 Mb of HTML. And HTML is often more reasonable than any amount of Javascript/JSON (for the same reasons why static text can be more reasonable than executable code). – user1643723 Mar 16 '17 at 03:22
  • 1
    @Andy: Yes, but you have to perform the same lifting to display it in both cases. The server obviously does not store the data solely as rendered HTML in the database. There's no difference between rendering it to HTML on the server and sending it to the client and having the client render it to HTML, except that rendering it on the client isn't shit. – DeadMG Mar 16 '17 at 12:55
  • 1
    @R.., care to elaborate ? If your application has that level of security requirements, where you can't even trust the connection you opened with the server or the server response, I'm pretty sure that it's not the type of data alone that will meet your requirements. It's like you're already [on the other side of the airtight hatchaway](https://blogs.msdn.microsoft.com/oldnewthing/20060508-22/?p=31283). – Machado Mar 16 '17 at 13:18
  • @Machado: That's not tight, it's minimal. In all cases you need to be concerned about XSS and other injection-type attacks. If you're accepting large amounts of mixed code/data, you have a huge amount of server-side code processing that which you have to audit. If you're just accepting data that can't contain code, the scope of what you have to audit is massively reduced. – R.. GitHub STOP HELPING ICE Mar 16 '17 at 16:09
  • 1
    @R.. you still have to be concerned with XSS by responsing JSON. It's like I said, if you have that level of security / auditing requirements, it's not the type of the response alone that will make your application secure. It's easy to find samples of how to XSS with JSON, and the problems you face are basically the same wheter your application send responses with HTML or JSON. [Here](https://security.stackexchange.com/questions/149871/xss-from-json-outputs) and [here](https://security.stackexchange.com/questions/149871/xss-from-json-outputs) for example. – Machado Mar 16 '17 at 16:28
  • "... what you are losing by not using JSON/XML is basically the possibility to use your endpoint as an API" You shouldn't be losing this possibility. HTTP Content Negotiation allows a request to specify whether it wants HTML / JSON / XML from an endpoint, so a server can give HTML to browsers and JSON to code attempting to use your endpoint as an API. You can give HTML by default (not necessary though as browsers explicitly ask for it) and add JSON / XML support later in a backwards-compatible way. – Jack Mar 16 '17 at 16:58
  • @Machado: That's only possible if you're misusing types; if there's any level of rigor to how you handle the data, it simply doesn't happen. This was a solved problem decades ago, and the only reason it keeps resurfacing is developers using stone-age practices. – R.. GitHub STOP HELPING ICE Mar 16 '17 at 17:16
  • @R.. why wouldn't this also be true when responsing HTML ? – Machado Mar 16 '17 at 17:55
  • 1
    "Responsing" HTML *is* a stone-age practice. Applying enough guarantees to let a potential new user get the data easily means that you're effectively returning JSON anyway, just with some odd syntax. – DeadMG Mar 16 '17 at 19:14
  • 5
    Serving HTML over HTTP? What is this? A website? – Ant P Mar 16 '17 at 21:07
  • @DeadMG Sure there's a difference; if you just need to present data, building the HTML on the server reduces / eliminates the need to work with JS and build out another application in JS to handle getting data & formatting it. Generally it will be easier to do it that way, meaning less cost to the person paying the developer. In other words, sometimes an API like you're describing is over-engineering. I suspect though you're never going to change your opinion, so we can end this here. – Andy Mar 16 '17 at 22:40
  • " the HTML is already there, it's just a matter of parsing the elements and rendering them". Precisely, rendering DOM objects takes time. What's most efficient in terms of rendering data seems to be having the markup already rendered and then update its values/innerTexts from an AJAX json. – Marc Compte Mar 17 '17 at 11:56
  • What's most efficient at runtime and what's best practice often diverge. However, my company maintains a mobile website for iOS, which we run on the worst possible hardware (an iPod Touch so old it isn't in support by Apple anymore) and we use React for everything, so I find it hard to believe that client-side rendering actually takes a problematic amount of time. – DeadMG Mar 17 '17 at 12:25
  • @Andy You're basically building the same infrastructure in both cases. The only difference is that putting it in JS means that you can use some libraries that are not shit, you need to use a bunch of JS anyway for interactivity, and you can avoid completely pointless client/server coupling. Much like many other choices, just returning HTML blobs from the server may seem like the quickest option but in the long run, it's just technical debt that you will have to pay off. It's simpler to just do it right the first time. – DeadMG Mar 17 '17 at 12:27
51

JSON and HTML fulfill two different semantic purposes.

If you are populating a web page with data, use JSON. If you are building up a web page from portions of web pages, use HTML.

They may kinda sound like they're the same thing, but they aren't, at all. For one thing, when you are building up a portion of a web page using HTML returned by the server, you are working server-side. When you are binding data to a web page, you are working client-side.

Also, you have to be careful with HTML to not tightly-bind to a specific page. The whole point of rendering partial pages in this way is for the partials to be reusable, and if you make the partial too specific, it won't compose to other pages. JSON doesn't have this problem, because it's just data, not web page structure.

Robert Harvey
  • 198,589
  • 55
  • 464
  • 673
  • 1
    "For one thing, when you are building up a portion of a web page using HTML, you are working server-side." Why? I see no reason why this should be the case. It's only obviously true for the initial page load and arguably, not even then since the client can make requests for the data it needs. – DeadMG Mar 14 '17 at 21:34
  • 3
    @DeadMG It should say "when you are building up a portion of a web page using HTML returned by the server" (as opposed to using JSON returned by the server) – user253751 Mar 15 '17 at 02:01
  • Indeed, but since there is little motivation for that to ever be the case, I don't see the point. – DeadMG Mar 15 '17 at 11:11
  • 6
    @DeadMG Little motivation for what to ever be the case? For the server to return HTML? That is literally what this whole SE question is about. – user253751 Mar 15 '17 at 23:20
  • The question is about whether or not you should return HTML. It's clear that the initial response must be HTML but there's no obvious reason why any other APIs should return HTML. – DeadMG Mar 16 '17 at 15:10
23

The main problem is that it tightly couples the server to the client, who must know the HTML structure. It also makes the endpoints more difficult to re-use in new ways or new applications.

Returning plain data and letting the client render it decreases coupling and increases flexibility and testability- you can run unit tests on the client for mock data, and run unit tests on the server to test the desired data.

DeadMG
  • 36,794
  • 8
  • 70
  • 139
  • 11
    HTML can be made reasonably generic. You can return a bulleted list, for example, and stuff it into a div, where it will be subject to styling by the prevailing CSS. – Robert Harvey Mar 14 '17 at 16:16
  • 10
    That's not all that useful if I need to stuff it into a span this time. Or render it in another application which is not rendered in HTML. – DeadMG Mar 14 '17 at 19:50
  • True. Returning HTML only makes sense if you're composing HTML. You could potentially parse it, but that's not ideal. – Robert Harvey Mar 14 '17 at 20:43
  • 2
    I would rephrase as *will always be* composing HTML, and the form of that HTML must always be completely consistent across all usages, which is not a very helpful guarantee. For instance, in our app we have lists, but we actually didn't use `ul` and `li` but instead changed to making each one a `div` (don't remember why). Would have been tricky if the server returned a bunch of HTML with `ul`s and `li`s in it. – DeadMG Mar 14 '17 at 21:25
  • Which is why this sort of composition usually takes place on the server (not the client), where you can reasonably expect such guarantees. – Robert Harvey Mar 14 '17 at 21:28
  • 2
    Seems pointless to get the guarantee in the first place when you can just return the data and let the client render that as HTML as it sees fit (if it's even going to render it at all) – DeadMG Mar 14 '17 at 21:29
  • Well, SPAs and client-side rendering are the new hotness. In the old days, the kind of HTML composition I described is how it was done, and it's still useful in some scenarios. – Robert Harvey Mar 14 '17 at 21:31
  • 1
    The only scenario I can see where returning HTML would be preferable is if the client doesn't have enough resources to do the rendering itself. – DeadMG Mar 14 '17 at 21:32
  • I agree with Robert Harvey. Even if there's a secondary user not using HTML, parsing a plain HTML `...` is not hard. Of course, if ýou don't use CSS as Robert suggests, and return a formatted HTML list, then you'll have a slightly bigger issue. – MSalters Mar 15 '17 at 12:56
  • 1
    It's not hard, it's just completely pointless. – DeadMG Mar 15 '17 at 21:15
  • 1
    This answer is based on the faulty assumption that a given endpoint should necessarily be designed to serve more than a single client. Realistically if you are serving data directly to a web page your API (JSON or otherwise) is specialised for that single purpose and actually using that endpoint for anything else is usually ill-advised anyway as it forces you to maintain support for two potentially diverging use cases in a single contract. – Ant P Mar 16 '17 at 21:17
  • @JimmyBreck-McKye: I don't think I made that assumption. My assumption was that the endpoint returns unstyled HTML that is styled by the *prevailing* CSS, meaning the CSS that has already been loaded from wherever. – Robert Harvey Mar 17 '17 at 14:35
  • You don't need to maintain support for two diverging use cases. It's the same use case - "Just give me the data". Every endpoint should be designed to be minimally coupled- that's just basic sense. – DeadMG Mar 18 '17 at 00:03
  • Robert is right that server side rendering does still have its advantages. It's a somewhat better user experience if you can get away with it: less time loading, less data to download, NoScript can stay on, avoids the need for front-end templates, less likely to break standard menus/keys, etc. @MSalters Parsing arbitrary HTML is pretty hard without a parser and a search mechanism. Which browsers do have, but you're still relying on something that is likely to change to make things look better on some other page. – jpmc26 Mar 18 '17 at 00:54
  • This was a great explanation @DeadMG – visc Oct 24 '17 at 13:36
14

I think you have it a little backwards. You say:

we have no test whatsoever, so we have no particular reason to create this JSON endpoint

A reason to use a proper endpoint would be so that you could test it. I'd say that having no tests is a very good reason to start writing some. That is, if there is any logic that would be suitable to test.

200k lines of code is a lot to refactor and are probably hard to maintain. Breaking out some endpoints and testing them might be a good place to start.

Another reason might be to separate the server from the client. If, in the distant future, the application design or layout changes, it's easier to work with a proper data format than HTML output. In an ideal world, you would only have to change the client and not touch the server at all.

Victor Sand
  • 249
  • 1
  • 5
  • The point about layout changes sounds more like a need to separate *templates* from the underlying data, but there's no reason those templates have to be on the client. Indeed, there are plenty of reasons for them *not* to be, e.g. you can't decide to hide data from the client if your rendering is on the client. HTML partials can be re-skinned just fine if they're output by the same templating system as full HTML pages. – IMSoP Mar 15 '17 at 10:09
6

There are 3 ways (at least?) to build up a web page:

  • Generate the entire page server side.
  • Return a bare bones page from the server plus code (JavaScript), and have the page fetch its data and render into HTML client side.
  • Return a partial page plus code, and have the code fetch pre-rendered blocks of HTML that it can drop into the page.

The first one is fine. The second one is also fine. It's the last one that's the problem.

The reason is simple: you have now divided the construction of the HTML page into completely disconnected parts. The problem is one of maintenance. Now you have two separate entities in charge of managing the details of the UI. So you have to keep CSS and other similar details in sync between the two separate pieces. You changed the width of the side bar? Great. Now the HTML fragment that comes back causes horizontal scrolling because its assumptions about the side bar width no longer hold. You changed background color for that block? Great, now your HTML fragment's font color clashes because it assumed a different background color and someone forgot to test that endpoint.

The point is that you have now split up knowledge that should be centralized in a single place (namely the presentation logic), and this makes it more difficult to make sure all the pieces fit together correctly. By using a JSON API, you can instead keep all that logic in just the front end, or you can keep it all in your server side templates if you render your data into HTML to begin with. It's about keeping the presentation knowledge/logic in a single place, so it can be managed consistently and as part of a single process. HTML/CSS/JS is difficult enough to keep straight without breaking it up into a lot of tiny pieces.

JSON APIs also have the additional benefit of making the data available completely independently from the presentation logic. This allows multiple, different presenters, such as both a mobile app and a web page, to consume the same data. In particular, it enables consuming the data without a browser (such as mobile apps or nightly cron jobs); these consumers may not even be able to parse HTML. (This of course necessarily relies on having a situation where the data is the same between the different consumers, or one can use a subset of the other.) Whether you need this ability depends on your particular application's requirements, though, while managing your presentation logic is necessary regardless. I will say that if you implement it up front, though, you'll be better prepared for future growth.

jpmc26
  • 5,389
  • 4
  • 25
  • 37
  • 2
    I actually think avoiding duplicate display logic can be a good reason *to* render HTML page fragments: if you render part of the page on the server (e.g. the header and basic layout), then generate other parts based on JSON data on the client, you have two different sets of templates. Rendering partials on the server moves this logic *back* to your central presentation layer, which can use the same template to render an individual component as it would if it was assembling the whole page statically. – IMSoP Mar 15 '17 at 10:17
  • 1
    you're the only one who mentions mobile, I want to give you a thousand upvotes for that – Lovis Mar 15 '17 at 15:34
  • 1
    @IMSoP If you need a *dynamic* page, then you have to have front end logic. If you still render fragments server side, now you have to make sure the front end's assumptions match the pre-conditions of the server constructing the fragments. You can't break that dependency. Keeping that knowledge in sync is harder if it's split up into completely divided systems. If you just render on the front end, those assumptions are centralized. I think I'd also avoid mixing a dynamic front end with an initial state in a server side template; a "bootstrap" to start the front end is simpler. – jpmc26 Mar 16 '17 at 19:32
4

I would say there is nothing wrong with the server returning an HTML fragment and the UI assigning it to .innerHTML of some element. This is, in my opinion, the easiest way to develop asynchronous JavaScript code. The benefit is that as little as possible is done using JavaScript and as much as possible is done in a controlled back-end environment. Remember that JavaScript support in browsers varies but your back-end always has the same version of the back-end components, meaning that doing as much as possible in the back-end will mean as little as possible version incompatibilities.

Now, sometimes you want more than just an HTML fragment. For example, a status code and an HTML fragment. Then you can use a JSON object that has two members, statusCode and HTML of which the second can be assigned to .innerHTML of some element after checking the statusCode. So, using JSON and using innerHTML are by no means alternative exclusive approaches; they can be used together.

By using JSON you can even have multiple HTML fragments in the same response which get assigned to the .innerHTML of multiple elements.

In summary: do use .innerHTML. It makes your code compatible with as many browser versions as possible. If needing more, use JSON and .innerHTML together. Avoid XML.

juhist
  • 2,579
  • 10
  • 14
4

There is nothing wrong in principle. The question is: What do you want to achieve?

JSON is perfect for transmitting data. If you send HTML instead and expect the client to extract the data from the HTML, that's rubbish.

On the other hand, if you want to transmit HMTL that is going to be rendered as HTML, then send it as HTML - instead of packing the HTML into a string, turning the string into JSON, transmitting JSON, decoding it on the other side, getting a string, and extracting the HTML from the string.

And just yesterday I ran into code that put two items into an array, turned the array into JSON, put the JSON into a string, put the string inside an array, turned the whole array into JSON, sent it to the client, which decoded the JSON, got an array containing a string, took the string, extracted the JSON from the string, decoded the JSON, and got an array with two items. Don't do that.

gnasher729
  • 42,090
  • 4
  • 59
  • 119
  • +1 Exactly. The first question is, what do you need to receive? There would be little wrong with an endpoint returning sidebar ads as a bit of HTML, or perhaps a footer, or similar elements. – SQB Mar 18 '17 at 10:36
3

This all depends on the purpose of the API, but generally what you describe is a pretty strong violation of separation of concerns:

In a modern application, API code should be responsible for data, and client code should be responsible for presentation.

When your API returns HTML, you are tightly coupling your data and presentation. When the API returns HTML, the only thing you can do (easily) with that HTML is display it as some part of a larger page. From a different angle, the only thing the API is good for is supplying your page with HTML. Plus, you've spread your HTML across both the client and server code. This can make maintenance a headache.

If your API returns JSON, or some other form of pure data, it becomes much more useful. The existing app can still consume that data, and present it appropriately. Now, though, other things can use the API to access the same data. Again, too, maintenance is easier - all the HTML resides in one place, so if you want to re-style the whole site, you have no need to change your API.

SouthShoreAK
  • 340
  • 1
  • 4
  • 5
    "In a modern application, API code should be responsible for data, and client code should be responsible for presentation." Why should this always be the case? I agree that this is a common pattern and that it makes certain things easier, but I see no reason to elevate it to the level of "should" ... It is a decision that needs to be taken on a case by case basis, and there are certainly reasons why in some situations you may want to make a different decision. – Jules Mar 14 '17 at 23:37
  • @Jules because if you have an API and a client, having both in charge of rendering is a violation of separation of concerns. (Now, you don't necessarily have an API and a client. You can have only one component, and have it do the whole presentation. But then you don't have an API) – njzk2 Mar 15 '17 at 02:20
  • @njzk2 Just because an API delivers HTML data does not mean it has rendered it. It may be treating the HTML as a blob and storing it in a database, for example. Also, some rendering may be required on the server rather than the client (eg providing static pages for search engines) so reusing that capability could be seen as elimination of duplication. – Jules Mar 15 '17 at 12:13
  • 1
    Also, it is entirely possible to produce a client and api pair where all rendering occurs at the server and the client merely plugs delivered HTML into predefined slots in it's DOM. Jquery has an entire module dedicated to this kind of client, which suggests to me they must be reasonably common. – Jules Mar 15 '17 at 12:20
  • 1
    @Jules lots of things are reasonably common, that's not a reason why they are reasonable. – njzk2 Mar 15 '17 at 16:12
  • @Jules sure thing, but in that case this is not an api, as it is commonly defined – Benoit Mar 16 '17 at 02:51
2

HTML is tied to a specific design and use.

With HTML, if you want to change the page layout you need to change how the html is generated by the server call. Usually, that requires a back-end programmer. Now you have back-end programmers, who by definition aren't your best html writers, handling these updates.

With JSON, if the page layout changes, the existing JSON server call doesn't necessarily have to change at all. Instead, your front-end developer, or even the designer, updates the template to produce the different HTML you want from the same basic data.

Additionally, the JSON can become the basis for other services. You might have different roles that need to see the same basic data in different ways. For example, you may have a customer web site that shows data about a product in an order page, and an inside sales page for reps that shows the same data in a very different layout, perhaps alongside some other information not available to general customers. With JSON, the same server call can be used in both views.

Finally, JSON can scale better. In recent years we've kind of gone overboard with client-side javascript frameworks. I think it's time to actually take a step back and start thinking about what javascript we're using, and how it affects browser performance... especially on mobile devices. That said, if you're running a site large enough to require a server farm or cluster, instead of a single server, JSON can scale better. Users will give you processing time in their browsers for free, and if you take advantage of that you can reduce the server load in a large deployment. JSON also uses less bandwidth, so again, if you're big enough and use it appropriately, JSON is measurably cheaper. Of course, it can also scale worse, if you end up feeding 40KB libraries to parse 2KB of data into 7KB of html, so again: it pays to be aware of what you're doing. But the potential is there for JSON to improve performance and costs.

Joel Coehoorn
  • 1,895
  • 4
  • 17
  • 22
1

There is nothing wrong with such an endpoint if it fulfills its requirements. If it is required to spit out html that a known consumer can parse effectively, sure, why not?

The problem is that, for the general case, you want your endpoints to spit out a payload that is well-formed and effectively parse-able by a standard parser. And by effectively parse-able, I mean, parse-able declaratively.

If your client is forced to read the payload and pry open information bits from it with loops and if-statements, then it is not effectively parse-able. And HTML, being the way its, it is very forgiven in not requiring itself to be well-formed.

Now, if you make sure your html is xml-compliant, then you are gold.

With that said, I have a significant problem with this:

I'm gonna tell you this: an endpoint that returns HTML reduces your dependency on JavaScript libraries and reduces the load on the user browser since it won't need to interpret/execute JS code to create DOM objects - the HTML is already there, it's just a matter of parsing the elements and rendering them. Of course, this means we're talking about a reasonable amount of data. 10 megabytes of HTML data isn't reasonable.

That's a bad idea no matter how you cut it. Decades of collective industrial experience has shown us that, in general, it is a good idea to separate data (or model) from its display (or view.)

Here you are conflating the two for the purpose of speedy JS code execution. And that's a micro optimization.

I've never seen this as a good idea except in very trivial systems.

My advise? Don't do it. HC SVNT DRACONES, YMMV, etc.

luis.espinal
  • 2,560
  • 1
  • 20
  • 17
0

It's difficult to categorize a right or a wrong. IMO, the questions I'll ask are: "should it", or "can it do with less?".

Every endpoint should strive for communicating with as little content as possible. The signal-to-noise ratio is typically HTTP codes < JSON < XHTML. In most of the situations, it's good to chose the least noisy protocol.

I differ on the point about client browser load by @machado, as with modern browsers this is a non-issue. Most of them are equipped in dealing with HTTP codes and JSON responses pretty well. And although you don't have tests at the moment, long term maintenance of a less noisy protocol would be cheaper than the one above it.

Peter Mortensen
  • 1,050
  • 2
  • 12
  • 14
hazardous
  • 109
  • 2
0

JSON is just a textual presentation of structured data. A client naturally needs to have a parser to process data but virtually all languages have JSON parser functions. It is much more efficient to use JSON parser than to use HTML parser. It takes little footprint. Not so with an HTML parser.

In PHP, you just use json_encode($data) and it's up to the client on the other side to parse it. And when you fetch JSON data from a web service, you just use $data=json_decode($response) and you can decide how to use data like you would do with variables.

Suppose you develop an app for a mobile device, why do you need the HTML format when mobile apps rarely use the web browser to parse data? Many mobile apps use JSON (most common format) to exchange data.

Considering that mobiles are often on metered plans, why do you want to use HTML that takes much more bandwidth than JSON?

Why use HMTL when HTML is limited in its vocabulary and JSON can define data? {"person_name":"Jeff Doe"} is more informative than HTML can provide about its data since it only defines structure for HTML parsers, not define data.

JSON has nothing to do with HTTP. You can put JSON in a file. You can use it for configurations. Composer uses JSON. You can use it to save simple variables to files as well.

netrox
  • 146
  • 4