
Do we need a web API? - feross
https://liaison.dev/blog/articles/Do-We-Really-Need-A-Web-API-yq12wz
======
briandilley
RPC - this isn't anything new.

When I started doing web development in the late 90s for about ~5 years I was
the designer, front-end, and backend developer all in one. Then over time
things changed to allow for specializations and we now have many different
functions, and that's a good thing. RPC has a place, and it's not for web
apps, at least most of the time.

I've noticed over the years that JavaScript developers tend to try and put
their JavaScript everywhere and I often wonder if it's because they don't want
to learn other technologies. Don't get me wrong, I like a little bit of JS too
- I even added JavaScript support to an old 2D Game engine using SpiderMonkey
(before V8 was a thing) back in the day so that I could make desktop games
with JavaScript. I just don't want to do _everything_ with JavaScript.
Especially with so many interesting languages and technologies to play with
these days.

Are JavaScript developers today the PHP guys of the past?

~~~
z3t4
Wouldn't you prefer to talk in your mother language instead of using a new
language for every country you visit?

~~~
adjkant
At first, but not if it made it harder to communicate in each country I
visited if I was visiting those countries regularly. I think the parent is
likely onto something in that the spread of JS into backend services is not
beneficial to those who spend most of their time on the backend, but it
beneficial to those who don't. That's IMO creating an inherent tension.

Personally I have never understood backend JS as you get untyped, weird silent
errors, under or completely un-utilized async features that end up causing
more problems than they solve, and then all the quirks of JS to boot. I
regularly hear the argument of the benefits of keeping the language the same
on both ends, but besides slightly easier JSON between them (something handled
by clean packages in almost every language these days with minimal
effort/LOC/boilerplate) the languages don't end up actually sharing a ton
given how you hook into a web framework like Express, database API's, etc. You
don't get code reusability and I don't think the JS tradeoffs are worth the
slight savings on context switching. If you have a serious project of any
scale/long term use and have front end programmers that want to use JS on the
backend, either bite the bullet and have them learn now or hire some backend
devs in a language better suited to your project.

~~~
z3t4
As someone coming from web dev to back-end JS I take with me the love for
instant feedback, which allows for extensive manual testing during
development. And I also use automatic regression tests before pushing to prod.
Node.js is infamously known to use small modules, it however gives you battle
tested code run by thousand in production.

I usually take a front-end first aproach, but there are also lots of people
taking a backend first aproache where they rely more on static analysis,
compilation, unit tests and packaging - rather then manually testing every
LOC.

~~~
adjkant
Is there anything you said that is specific to JS?

> the love for instant feedback

What languages can you not get this with?

> And I also use automatic regression tests before pushing to prod.

That's 100% language agnostic...

> Node.js is infamously known to use small modules, it however gives you
> battle tested code run by thousand in production

Many other languages have extensive packages pulled in, but that says nothing
about how battle tested the code is unless all of the packages have high use.
Python has plenty of packages with the same use level. Java has tons as well.
The list goes on.

~~~
z3t4
In the past when people have asked me questions like those they usually knew
the answers. So may I ask, Why you are asking?

~~~
bmn__
He's calling you out on the wild claims in your post that are not particularly
nuanced or unbiased.

You shouldn't try to pull a fast one on HN readers, it won't work most of the
time.

------
flexblue
As other have noted, someone caught on to the simplicity of RPC.

It always baffled me how so-called RESTful APIs became popular, despite
virtually all of them being RPC APIs with a veneer of rather pointless HTTP
semantics.

Virtually none of those APIs do anything to serve the intentions and goals
behind REST[1]. Furthermore, many RESTful APIs end up being wrapped into
language-specific clients anyway, because they have poor ergonomics in their
raw state.

I consider RESTful APIs the most significant anti-pattern not widely
recognized as such.

[1]
[https://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arc...](https://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm)

~~~
tasubotadas
> the simplicity of RPC

Simplicity? Have you ever tried to integrate distributed applications that do
not share the same codebase?

And calling REST anti-pattern tells me that you aren't that familiar with
alternatives.

>despite virtually all of them being RPC APIs with a veneer of rather
pointless HTTP semantics.

If you want to do RPC over HTTP and pretend that it is REST interface, it
isn't really a problem of REST.

------
zemnmez
this is just JSON RPC? The "constantly serialize and deserialize it" statement
is totally untrue too... The frontend makes 6 XHR calls just to render a
single page and they're all just JSON. The idea of the frontend 'just calling'
the backend with no API boundary is nothing short of atrocious for security.

The only feasible logical end to this is ASP, which was an interesting idea
when it was launched 19 years ago

~~~
mvila
This has nothing to do with JSON RPC. Liaison uses Deepr
([https://liaison.dev](https://liaison.dev)) as a communication protocol.

Regarding the number of XHR calls, to be accurate, it is not 6 but 4. Once
Liaison is complete and optimized, the number of calls should drop to 2.

Also, please keep in mind that Liaison is made for building single-page
applications. So, using it for a simple blog might not be the right choice.

And about your security concern, please head over here:
[https://news.ycombinator.com/item?id=21660785](https://news.ycombinator.com/item?id=21660785)

------
theon144
In my view you just replaced an explicit API built on top of known protocols,
by a semi-magical implicit API.

The problem of serialization, deserialization, versioning, endpoint design...
They aren't an artifact, they're intrinsic to how Web apps are built.

But yeah, for small projects I think this could be really neat.

~~~
collyw
Having a properly defined API gives you a nice interface to test.

------
al2o3cr
CORBA called, they want their ideas back

~~~
icebraining
Even in JS, the Meteor framework was basically created to implement this.

Except they actually implement things like validation, because as much as one
may want to unify both environments, the reality is that exposing all your
methods to the outside world may have some pitfalls, to put it mildly.

~~~
collyw
What ever happened to Meteor? It was flavour of the month a few years ago,
with many a frontend dev ranting about how great it was. Now seems to be
forgotten about.

~~~
pkage
Hassles with installing NPM packages (they used their own package manager
(!)), it was incredibly heavyweight, baked in reliance on MongoDB, and a weird
templating language caused a kind of death-by-a-thousand-cuts situation.

Plus, React came out and blew Meteor out of the water.

~~~
dankohn1
One of the early Meteor developers, Evan You, went on to create Vue.js.

------
Quarrelsome
Its good that expensive operations are explicit. Every now and then developers
forget this and create garbage applications using frameworks that are set out
in similar ways to this.

Don't hide the communication layer pls.

------
thdrdt
There are already frameworks doing this. For example Blazor (.Net core 3) and
Phoenix Live View (Elixir).

They write the Javascript for you but you won't even notice it.

I don't have experience with Phoenix, but with Blazor I just write my complete
SPA in C#. There is no API for communication between the server and client.
Blazor creates all the JavaScript websocket code for me so I never need to
write a single line of Javascript.

And when you separate your business layer from Blazor you can always add an
API in the future when you need one. Just create some controllers for your API
and use the same business code Blazor is using.

------
daxfohl
First Law of Distributed Object Design: "don't distribute your objects"

\--Martin Fowler

~~~
mvila
A Liaison backend is stateless, so there is no shared state to worry about.

------
fyp
Pouchdb/firebase/backend-as-a-services were supposed to be the answer to
getting rid of CRUD apis. The problem is authorization and validation becomes
really difficult if you don't have a backend that you can trust.

~~~
TOGoS
10 years of writing web application backends has taught me that yes,
authorization is indeed the reason we all still have jobs. And the occasional
handling of a transaction failure.

------
peteforde
As has been noted in other comments, there is a growing list of technologies
that implement some variation of RPC such that events on the client trigger
server events. Those events persist any data changed and then regenerate the
current state of the UI and ship the diff back to the client, ideally via
calls to the morphdom library.

What frustrates me is that it's not the API that is the source of complexity.
~80% of the pain of building most apps comes from managing the syncronization
of state between the client and server. SPAs are the over-prescribed opiates
here making the problem worse. Imagine what could be possible if you walked
away from maintaining client state altogether.

We did, and it's wonderful. StimulusReflex let me build a reactive tabular UI
with sorting, filtering and pagination with 115 LOC, none of which is custom
JS:
[http://expo.stimulusreflex.com/demos/tabular](http://expo.stimulusreflex.com/demos/tabular)

I honestly believe that the existence of things like StimulusReflex and
LiveView demand we question the ongoing utility of libraries like React.
Popularity is not a good reason to use something, especially when you realize
you could be radically more productive if you don't use it.

------
daxfohl
Things like this have been tried many times before. (I made one myself back in
the day). It always seems like a great idea up front, but never ends up quite
working out.

One of the big things is that the benefit declines over time. The amount of
code reuse you get is sub-linear with respect to the size of the project. As
the project matures, GUI code and back end code diverges. That leaves you
stuck in a framework that ends up not necessarily optimal for server side, and
not necessarily optimal for client side, and the amount of code you end up
writing to coordinate between them ends up outweighing the actual business
logic.

The things that are successful tend to focus on problems that increase with
greater than linear complexity as your app matures. Spend time focusing on
these instead. Don't lock yourself into a framework that prohibits it.

~~~
mvila
Your point is valid, but Liaison allows you to build different layers if you
wish.

If you worry about cluttering the business logic and want to clearly separate
the exposed API, you can expose subclasses of your domain models instead.

~~~
daxfohl
I'd still say the established routine of publishing a public API and any
shared code can go into NPM or whatever is the better approach.

Liaison and tools like it essentially create a monolith exactly where
something is screaming to be two separate services. You want to be able to
deploy versions of server side and client side code independently. You want to
be able to ensure you don't break clients that have web pages open when you
deploy the new server version. You want clients to be able to run where JS
isn't available.

~~~
mvila
About API versioning, the problem is the same as any web API. It's possible to
add backward-compatible changes, otherwise, you need to fork the backend into
a new endpoint.

About interoperability with non-JS environments, I wrote an article about
that: [https://liaison.dev/blog/articles/How-about-
interoperability...](https://liaison.dev/blog/articles/How-about-
interoperability-oy3ugk)

~~~
daxfohl
I don't mean to knock it. It's a cool project and obvious you've done some
good work on it. But, I wouldn't expect it to lead anywhere beyond a couple
sample POC apps. It's been tried before and never quite seems to work out (I
did something similar with VB6 forms way back when. It didn't work out.
Meteor.js is one that probably came the closest to real-world success. It
didn't work out.). There was a bit more interest in this approach back when
SPAs were just coming onto the scene, but in the time since, the programming
community seems to have converged around the idea of well-defined boundaries
and interfaces, allowing use of the best tool for the job in each individual
service, and abstracting out the distributed communication layer with a
metaprogramming tunneling approach has somewhat fallen out of favor.

If your goal is just a brain workout then by all means keep going with it. But
if you're looking to do something that gets some larger adoption, then I'd
probably wrap this up and move on to the next thing.

(Not that you asked my advice, or that I'm in any way qualified to give it)

------
vbezhenar
Having clear API allows to have a clear boundary between trusted and untrusted
environment in backend. If you don't check your arguments in REST endpoint,
it's obvious bug and easy to spot. If it's just another method, well, you're
not treating input in every function as a hostile.

~~~
mvila
Please see my answer here:
[https://news.ycombinator.com/item?id=21660785](https://news.ycombinator.com/item?id=21660785)

------
sm_sohan
Many years ago I remember using a similar shim on ASP.NET where you'd simply
decorate a server-side C# method and you could call it from JS like any other
method. Not quite the way done here, but it had similar goals to blend server
and client. So far, these things don't work in practice because of the so many
things that differ between a browser and server environment.

[https://docs.microsoft.com/en-
us/dotnet/api/system.web.scrip...](https://docs.microsoft.com/en-
us/dotnet/api/system.web.script.services.scriptmethodattribute?view=netframework-4.8)

------
johnhenry
I wish the "really" wasn't taken out of the HN title. It gives the title a
somewhat different meaning.

~~~
mvila
I wish that too. :)

------
k__
lol, coming from PHP, JSP and co, web APIs were the salvation.

Monoliths are a big problem and merging frontend and backend into each other
only made it worse...

------
ptx
The readme says: "The current state of an instance (i.e., counter's
attributes) is automatically transported back and forth."

How does this work? Do you need some cross-network locking mechanism when you
need to make sure the shared object's state doesn't get out of sync between
client and server?

What about passing object instances between client and server? Does it do what
(I think) DCOM does to handle garbage-collection of cross-machine object
references – keep-alives and timeouts?

~~~
mvila
A Liaison backend is stateless, so there is no shared state or garbage-
collection to worry about.

------
smitty1e
I daresay that if you need to:

a) scale, and

b) adapt over time

you're going to find yourself decoupling and slapping APIs on both ends to
adapt to the transport mechanism.

So for a boutique app, you might get away with a client-server model.

~~~
mvila
Liaison allows inheriting layers from each other. So, you can easily separate
your API layer with your model layer, and you don't need to build a web API
for that.

------
bilekas
This is an interesting project, but there are very good reasons for having
API's.

Its just about is it the right tool for the job.

I don't like their comment : _' They are just a necessary evil so the frontend
can communicate with the backend'_

~~~
icebraining
I'm sympathetic to your position, but right now your comment doesn't carry
much information. Why are they the right tool for the jobs? Which reasons are
those?

~~~
bilekas
Not to offer information, I'm just objecting to the stance they seem to make
that : "Hey we're solving the 'API' requirement problem' when there really is
no problem..

If your backend _only_ communcates with an SPA and nothing else, then yup,
this is a good tool for that job.

~~~
hatch_q
Actually this doesn't solve the core API challenges that SPAs have -
versioning and compatibility. Clients will simply run outdated frontend code.
Imho this is more trouble than worth as it will bring all the problems that we
had with WSDL.

If i'd do a SPA that has 'node' backend, i'd just use typescript to model the
API and you can have shared models and compile-time type safety.

------
dang
[https://news.ycombinator.com/item?id=21600859](https://news.ycombinator.com/item?id=21600859)
seems related.

------
gedy
I've used a similar concept about 10 years ago if anyone remembers Wicket[0],
and personally really liked it. The challenge was the UI and state were all
server side and difficult to keep memory usage down. I'd be interested in how
this model works now that client side UI and state are much more capable.

[0] [https://wicket.apache.org/](https://wicket.apache.org/)

~~~
fmakunbound
I liked it as well. Web development had gotten way harder over the last
decade.

------
namelosw
Actually RPC is a good idea for front-end to talk to backend.

Because the separation is more or less obligated if people wanted to do
interactive web pages, instead of people want to separate them as different
services for different problem domains.

People who don't like write JavaScript can stay tuned, as WASM age comes,
there would be a burst of things like this but not in JavaScript (eg: Blazor).

------
z3t4
Dont trust the client! Serialization should be abstracted. Btw. how does this
work without serialization? :P (I guess its abstracted). With an abstraction
layer, sending a request can just be an azync function call. There is also the
option to keep the front end stateless aka server rendering like in old school
web apps.

------
brillout
Have a look at Wildcard API[1], it's similar to what you are building.

I'm the author. I'm glad to see that RPC is getting more and more traction.

[1] [https://github.com/reframejs/wildcard-
api](https://github.com/reframejs/wildcard-api)

------
maxekman
A project using Elixir + Phoenix would be way cleaner if one would like to
leave out the API in web dev.

------
dekalbcountyman
isn't this a weak ass version of RPC/gRPC?

[https://grpc.io/](https://grpc.io/)

\- and thank God gRPC never took off the way Google hoped, it was pure ego and
politics like the majority of OSS projects these days (in the web world)

~~~
solipsism
Can you elaborate on the "ego and politics" part?

~~~
dekalbcountyman
I have a very personal history with gRPC

~~~
geitir
Is it bad? My operating systems class had a project based explicitly around it

------
SahAssar
As someone deploying frontend apps for a large site you should not
underestimate how long people have their tabs open. I can get sentry error
reports for versions that have not been deployed for months.

Does this handle "API" versioning in any real way?

~~~
mvila
For now, with Liaison, API versioning is no different than usual: preserved
endpoint for backward-compatible changes and new endpoints for breaking
changes.

------
aliswe
Seems like a WSDL endpoint from which you can generate eg. a client for .NET.

------
catern
Reminds me of
[https://github.com/pkamenarsky/replica](https://github.com/pkamenarsky/replica)
for Haskell

------
tasubotadas
It's always cute to see JavaScript developers reinventing things that have
been in the industry for 30 years. Welcome back RPC.

------
paulddraper
Postgraphile is an example of reducing the number of layers: directly expose
PostgreSQL schema (with row-level security) via GraphQL.

~~~
Apaec
But now you added the GraphQL layer on top of HTTP.

------
zwetan
one word: security

~~~
mvila
Liaison doesn't expose anything by default. Only the allowed attributes and
methods are exposed.

------
thanatropism
Does this force you to use node for the back-end?

~~~
mvila
For now, yes. Liaison is implemented in JavaScript, but the communication
protocol ([https://deepr.io](https://deepr.io)) is language agnostic. So it is
possible to imagine Liaison being ported to any languages in the future.

------
stopads
>Sorry, this site requires JavaScript to be enabled.

For a flat blog post? Like, seriously?

~~~
naringas
welcome to the web 2.0

cooming soon: web assemply web 3.0 which (I fear) might feel a lot like flash
web pages from the early 00s. I hope I'm wrong.

~~~
frenchyatwork
Web 2.0 was like 15 years ago now. Web 2.0 was "supposed" to be about
separation of style & content and gracefully degrading JavaScript.

I don't know want to call what we have now.

~~~
lubujackson
Probably the "Web App" or "Web SPA" era, since everything seems to need to be
a single page app that exists mostly in the client.

There are some benefits, of course. Stable and standardized UI is finally
available as a baseline for devs (much like early Windows/iOS software) and
all roads are clearly leading toward a unified design model for phone
apps/web/desktop. Bloat and needless complexity are the biggest issues at the
moment, but all the frameworks seem to be (finally) focusing on becoming more
snappy.

