Hacker News new | ask | show | jobs
by DSteinmann 3516 days ago
This has been reposted so many times by the author and by others that I can't help but finally ask.

What's the point? This would lead to your API being comprised of blocks of HTML which are probably only useable for one product. Why not just use REST + JSON? It would take no more than five minutes to set up client-side rendering, and you could even make it attribute-based like this with barely any more effort. Is it really not worth spending the extra five minutes it takes to set things up in a way that is reusable and standard? All I see is piles of legacy code being generated where it hurts most - in the backend.

This took me 10 minutes to cook up. It would have taken about three if I hadn't forgotten the jQuery and Handlebars APIs. This allows you to POST to a JSON API using two attributes. Untested of course, but you get the idea:

    Example: <button ic-post-to="/api/resource" ic-template="#a-handlebars-template" />

    $('[ic-post-to]').click((button) => {
        fetch($(button).attr('ic-post-to')), { method: 'post' })
        .then((result) => {
            let templateText = $($(button).attr("ic-template")).html();
            let template = Handlebars.compile(templateText);
            let resultHtml = template(result);
            $(button).replaceWith(resultHtml);
        });
    });
14 comments

> This would lead to your API being comprised of blocks of HTML which are probably only useable for one product.

Because for probably the majority of developers there IS only one product.

Here's what I think is happening. A bunch of us are working on websites that need to scale across multiple users and adapt to multiple clients and will have to grow and pivot as the business needs change. And they've learnt the hard way about building scalable systems.

But what is going horribly wrong is that their war stories and best practices and tools and processes are being used by a bunch of us who will never face those problems. And we're paying the price in terms of complexity for problems we aren't ever going to face.

If you're building a SaaS for a startup that might reasonably expect exponential growth, unfortunately your advice is being taken to heart by people building blogs and small web-shops and we're seeing some terrible technical decisions being made because everyone wants to do things 'right'.

We need a healthy dose of YAGNI drilled into people. Whatever happened to progressive enhancement? It still suits the vast majority of web projects perfectly well.

That's a great response Andy.

I'd also say that JSON APIs either tend to get tuned for specific UX needs or become more and more expressive. The first option calls into question the general, reusable nature of the API, and the second introduces security issues in an untrusted computing environment[1].

I typically split out the JSON API for my system from the web application proper so that my web application needs don't screw up the public API of the system. They end up being two separate concerns with different shapes, authentication methods, etc.

[1] - http://intercoolerjs.org/2016/02/17/api-churn-vs-security.ht...

This is where things like GraphQL come in.
Customers aren't going to use GraphQL for a public API, so you've just added another (micro) service to talk to the GraphQL server and translate it into a more traditional REST API (or the other way around if you want your internals to be REST). Also, you've pretty much forced an entire ecosystem of complexity onto your front end.

And then you've added a ton of complexity, bringing us full circle.

Based on the parent comments, we're talking about simple websites where serving HTML through AJAX is an effective approach. In the name of "purity", you've introduced JSON APIs, GraphQL, (most likely) React and Relay, more complex deployment with multiple services, probably a complex front-end buildchain, and who knows what else.

> Customers aren't going to use GraphQL for a public API

Why not?

Right now this isn't feasible. People are used to REST APIs, and the tooling and documentation (particularly outside of use with React and Relay) for GraphQL isn't where it needs to be for it to be feasible for a customer-facing API.
I started out agreeing with your sentiment, then found myself disagreeing with the premise behind it.

Yes, a lot of companies are founded around a single product or family of products. They can afford to use a building block that isn't re-usable across different projects. They're not making things for public consumption, or have multiple very divergent codebases.

But these aren't small web shops, and people building blogs. In the DC area at least, the above describes every midsized company ( midsized as in > $1 monthly revenue < $50 million monthly revenue). These guys are makers of the software that runs in doctors offices, hotels, non-profits, political organizations, and government contractors.

They're already bigger than most SasS companies in SV, can ever expect to be.

I oversimplified to make a point. If I could rephrase it in more general terms it would be something like "people in web development are taking engineering advice from people who are solving completely different problems" or maybe "best practice in web development is being framed by the atypical"
The short answer is: because the web architecture was and is fundamentally different than the 80's style client/server model you are advocating, and it has specific advantages that are being lost in the transition back to that model (security, scaleability, simplicity, etc).

The longer answer can be found in these posts:

http://intercoolerjs.org/2016/01/18/rescuing-rest.html

http://intercoolerjs.org/2016/05/08/hatoeas-is-for-humans.ht...

http://intercoolerjs.org/2016/02/17/api-churn-vs-security.ht...

Of course, you will need to go into all of this with an open mind, or you will not find any of it convincing.

In the first article you raised two issues about REST: Developers disagree on what it means to be "REST-ful", and HATEOS never took off, despite being the feature that distinguishes REST from other APIs.

In the second article you explained that HTML could implement HATEOS.

In the third article you argue that GraphQL is the natural progression of REST but its security model is complex to the point of being unsafe.

---

The first article, in my opinion, consisted of straw men arguments.

The second is understandable.

The third made no sense to me. With a system like GraphQL you can use a declarative column-based security model. This is, in my opinion, easier than the imperative stuff you're probably using to make your HTML endpoints secure. With GraphQL you need to set up your security constraints once. With HTML endpoints you need to remember to toggle off certain blocks of HTML for every single request. Is that what you're doing?

What were the strawmen in the first article? It is observable that REST/HATEOAS (HATEOAS in particular) are falling out of favor in JSON-based APIs. This is understandable because JSON is not a hypertext, and the rest of REST isn't amazingly useful without it. Where's the strawman?

I'm glad the second article makes sense.

The core point of the third article is that when you increase the expressive power of a JSON API (with something like GraphQL) you are putting this power in the hand of the end user, not just your developers. This is not the same as giving, for example, full SQL access to your server-side only developer, where the code is executing in a trusted computing environment.

> With GraphQL you need to set up your security constraints once

I'm only superficially familiar with GraphQL, (and not at all familiar with Intercooler), but I always felt that security was glossed-over and not a core part of what it offers.[0]

Authorization is challenging enough on the server, but having a query-language power client-side, feels like a pretty fragile thing to me to secure properly. Definitely not something you just set once and forget about...

[0] http://graphql.org/learn/authorization/ - if I get it right, it gives a good example of row-based authorization and essentially tells you to figure it out for yourself in your business logic layer.

> This has been reposted so many times by the author and by others

The author did post a story about intercooler four times in the last 3 years. Where is the problem?

> This would lead to your API being comprised of blocks of HTML which are probably only useable for one product.

Whats the problem with that if their is no need to reuse the API, or if there is no API at all, just a bunch of uncool php scripts?

> It would take no more than five minutes to set up client-side rendering?

Is client-side rendering better per se?

> Is it really not worth spending the extra five minutes it takes to set things up in a way that is reusable and standard?

What standard do you refer to?

I think it is obvious that this lib isn't meant to be the foundation for the next facebook app, be a contender for the current hip bloatware frameworks or might be the best lib for single page apps generally. But I can see lots of use cases where this lib will help to spice up some projects without getting burden under some boatload of unnecessary tooling and boilerplate codes.

The author did post a story about intercooler four times in the last 3 years. Where is the problem?

Look at the author's comment history, rather than story history. He has a reputation of plugging intercooler in every discussion related to JS. Not that I mind; but most of the "reposts" that GP is talking about are comments, not actual stories.

Good news: now that this broke through the noise I can relax on the shilling.

I assure you I am the person most relieved by this. ;)

I don't think there's anything wrong with sharing your work. This reminds me of a thread last week about sharing what you've made. https://news.ycombinator.com/item?id=12838751
Kudos to you for not giving up man.
I've seen he doing it before. The OP pushes Intercooler.js in every place.

Anyway, I'd like to thank him for it. It was because of this pushing that I learned about the lib, and I'm very glad for that.

> What's the point? This would lead to your API being comprised of blocks of HTML which are probably only useable for one product.

Only usable for one product? There aren't many platforms without UI layers that have some kind of component for rendering/presenting HTML these days. But even for those that don't:

> Why not just use REST + JSON?

Markup is as much a data-exchange format as JSON is. If you're writing/generating it well, anyway.

I'm not saying never use JSON (I have and do). I am saying it's a little weird, though, that we've somehow got to the point where anyone who's commenting on this discussion has forgotten that markup has done and can do the job JSON does, or that we're at a place where as an industry it seems weird or potentially an interop problem to serve markup instead.

Plus, unless I'm missing something, the typical case is just:

    if accept==html then return html(template, data)
    else return json(data)
Which is sure as hell less work than setting up React/Angular and a bunch of other junk on your HTML frontend to consume JSON and turn it into HTML in the browser. Probably higher performance, too, since JSON-consuming HTML frontends in the wild don't seem to exhibit (putting it mildly) the performance improvements that AJAX originally promised—then again, that X was XML (and remember XHTML? I, for one, really liked it) so it's not necessarily AJAX's fault that we've decided to rube-goldberg up the web the way we have.
Not everything needs a JSON API so any client can talk to it. You're also underestimating setting up client side rendering as my experience tells me otherwise.

Most of the time a django/rails rendered backend is desirable and easier to maintain over the long run.

The "point" is server-side vs client-side templating.

It's easiest to keep everything in one templating system and language. (Note: I said easiest, not most robust or ideal.)

Options:

1. Isomorphic code. This requires either NodeJS or compile-to-JS tooling.

2. Client-side-only: bad for SEO and usability.

3. Server-side-only: You either write several lives of boilerplate every time line your example, or use intercooler and write a single-liner.

What's wrong with "boilerplate with code-generator"?

For smaller sites, the number of parts often isn't huge, so boilerplate isn't a big deal.

I probably don't understand what you mean.

Generating code in a Turing-complete language use a program written in another Turing-complete language can get messy.

I mean scaffolding.

Just because something is turing complete doesn't mean that a generator has to be able to generate anything possible.

If boilerplate is an issue, scaffolding / code generators can be a quick fix.

Can I have intercooler do that scaffolding for me?
> Is it really not worth spending the extra five minutes it takes to set things up in a way that is reusable and standard?

HTML is standard. Even more importantly it has rich and standard semantics. Your homebrew protocol based on JSON is not and does not. You write an interpreter for it every single time without even realizing it.

The thing you cooked up in 10 minutes does not follow the principles of progressive enhancement. This immediately closes up lots of doors.

> All I see is piles of legacy code being generated where it hurts most - in the backend.

No problem. It's just views. If the need comes to make it general, and output JSON from everywhere, you just write another set of views. They are discardable. (And you'll probably need different URLs for the JSON anyway, so you'll probably keep both sets.)

so that i can render the html in microseconds on my server and not waste the users time, or have to write javascript
Also, in many cases you can cache the result so rendering is no longer happening anywhere, neither on the server, nor on the client.
So work is heavily bought into the idea of rendering the client-side content in front end services (what you call the backend). It lets devs change user-facing behaviour without invalidating cached minified assets (which saves money at scale). Plus, we can test client side behaviour in just a few browsers, and be reasonably confident that everything else will roughly be the same.

It works for us because the site is extremely static…

for a lot of the client side apps I create, I want the response to trigger potentially multiple listeners that are used in a composed fashion. It's a lot less efficient to write 1:1 logic for each endpoint.
you forget that some of us are lazy..
I was thinking the same thing. The only reason I think to use Intercoooler is for very simple scenarios, or for people who perfer the server side programming and want to minimise JS programming. Which I can relate to to some extent.

Having said that, I've been doing a side project in KnockoutJS and it isn't much harder than IC. You mark up the HTML and need a little bit of JS to call the api. So it would be like your example but with a line or two removed. And like your example as soon as you desire to do something custom you just add some more code.

On the service side you emit JSON instead of HTML and this can be easier IMO - virtually every language has a JSON library and you just convert your ORM objects to JSON (or just use them as-is!). That is less work than rendering HTML I would have thought.

you nailed it. I don't want to do JS. I know enough Python to get by, I'm writing a small webapp with some API hooks (internal webapp) and I'd like to have some AJAX-y components. While I don't know if this is powerful enough for everything, the idea of "click on <button> to retrieve data and place in <div>" is really awesome. Doing it in HTML-only is much easier for my peon-non-genius mind.
I agree. There are instances where I think returning HTML instead of JSON works (think of Rails Actioncable or Phoenix Channels), but I have a hard time conceptually understanding what problem is solved by this library.

Thinking of almost all of the full stack, I feel like you could have more flexibility with something like Rails with Angular on the front-end. You can set up a Rails controller to return JSON or HTML depending on the request type.

Throw in UI Router and have your Angular routes match your Rails routes... You can have your pages rendered server and client side and still have the flexibility to render JSON.

It would be sick if there was a stack where you can take make your routes more functional and have the routing work clientside and serverside. I know Turbolinks is supposed to solve this problem, but it sort of messes up how events are fired.

Also, Angular templates cannot be modified on the front end... but these intercooler attributes can.

I will admit, the author is probably solving a problem that I haven't encountered or even fully understand. If people are digging it, more power to him.

And that's how the monstrosities are born.
I work primarily with a legacy, enterprise PHP application and it is a monstrosity (large number of classes, breaking framework changes, deprecated front-end libraries, very old MVC patterns, heavily imperative).

There are elements that Rails (predictable routing, simplified MVC, templating rendering, and general ease of set up and deployment) and Angular (flexibility, directives, safe templates, state based routing, imperative but can be functional with filters) provide the feature set that I have described above (aside from the routing object idea for generating server and client side routing).

The underlying technologies are not important; Node already has isomorphic javascript. I think Phoenix might be on track to remove the need for a heavy use of javascript for creating a single page application by simply using channels.

However, I cannot speak on Node and Phoenix because I lack the experience with these languages to comment. I do have experience with Rails and Angular to generate an example of how I would like a full stack, AJAX heavy application to work.

Yeah he lost me at "angular"
Why? There are plenty of developers that use Angular.

If I speak from a place of experience, is that less valid if I use a language that you do not particularly like?

It is not always the correct language in a lot of cases, but it can be for creating the feature set that I have described above - an approach for a more functional application structure that would provide server and client-side routing without Turbolinks.

You don't even need Angular or Rails for this, but these are both tools that I have enough familiarity with to know that it would work.

Because 1) the appeal of intercooler is its simplicity, and 2) I don't know angular and don't have any desire to learn it. It looks complicated, and on the decline: http://stateofjs.com/2016/frontend/.

It's not a language it's a framework. And it will take me (and others on my team) time to learn it, and maintain it in the future. But if you like it, more power to you!