[HN Gopher] Data fetching on the web still sucks
       ___________________________________________________________________
        
       Data fetching on the web still sucks
        
       Author : bcherny
       Score  : 118 points
       Date   : 2021-01-27 16:26 UTC (6 hours ago)
        
 (HTM) web link (performancejs.com)
 (TXT) w3m dump (performancejs.com)
        
       | patates wrote:
       | What are examples of data-fetching libs/standards outside the
       | web, that check all (or a relevant subset) of those criteria?
        
         | dhritzkiv wrote:
         | I too am curious. All of the platform-specific frameworks which
         | do networking+datastore, that I've used, check even fewer
         | boxes. Especially when it comes to reactive UI and optimistic
         | responses.
        
       | gitpusher wrote:
       | The author does a good job of summarizing the relevant aspects of
       | fetching data in a modern web-app.
       | 
       | However, by NO means should all of this be handled by one "data-
       | fetching library" - as he suggests.
        
       | SimeVidas wrote:
       | I'm curious if the author thinks that people can actually read
       | the ultra-low-contrast text in the side column.
        
       | pier25 wrote:
       | Nobody has solved it because there is nothing to solve. That's
       | like saying that "we to optimize SQL for UX". No, no we don't.
       | 
       | Fetching data has nothing to do with managing state, rendering
       | UI, or even UX. Each layer has different problems it needs to
       | address.
       | 
       | And btw you can totally do GraphQL requests with fetch().
        
       | anderspitman wrote:
       | If your UI is complicated enough to worry about most things on
       | this list, maybe simplify your UI?
        
       | joshxyz wrote:
       | I'm currently experimenting with React and WebSockets and they
       | seem to be a perfect fit.
       | 
       | No need to write wrappers for Fetch, network errors and
       | reconnects can be handled on high-level, handlers for each
       | message type can be mounted and unmounted on useEffect hooks, all
       | back-end jobs can notify the user in realtime, all session-based
       | client-side data can be updated in realtime (in single or
       | multiple open tabs).
       | 
       | I'm also using uWebSockets.js[0] which is great in terms of API
       | design, stability, and performance. Their benchmarks[1] are just
       | convincing. Highly recommend people using ExpressJS / Koa /
       | whatever to try it.
       | 
       | [0] https://github.com/uNetworking/uWebSockets.js/
       | 
       | [1]
       | https://github.com/uNetworking/uWebSockets/tree/master/bench...
        
         | kekington wrote:
         | We are using Phoenix Channels[0] for a websocket-based app and
         | it's very easy to setup/work with. It should also scale easily.
         | 
         | [0] https://hexdocs.pm/phoenix/channels.html
        
           | joshxyz wrote:
           | When I was researching stuff I've read a lot of good things
           | about Phoenix, I honestly think socket.io and ws NodeJS
           | libraries are inferior compared to that.
           | 
           | It's just almost pure luck that the guy who wrote uWebSockets
           | (written in C & C++) also wrote NodeJS bindings, otherwise
           | we'll be stuck with the ones with sub-par api, docs, and
           | performance.
        
         | azangru wrote:
         | > and they seem to be a perfect fit
         | 
         | Needs a fairly capable server though, I suppose. One that can
         | handle lots and lots of open websocket connections.
        
           | IggleSniggle wrote:
           | Guess it really depends on how many concurrent users you
           | expect to have...
           | 
           | Sounds like 30 GiB RAM for 1 million concurrent users is not
           | unreasonable:
           | 
           | https://stackoverflow.com/a/17453704
        
           | joshxyz wrote:
           | Yes that's some genuine concern. Though on B2B and B2C SaaS
           | where you got paying users, I think each of them deserve a
           | websocket, and it could* alleviate some headaches for
           | developers.
           | 
           | * Anecdotal of course, at least for us.
        
           | e_y_ wrote:
           | Also your load balancer stack needs to support it, which is
           | becoming less of a problem these days but there's still some
           | stragglers. You could also end up with an imbalance where
           | some servers have a lot of connections and others have few.
        
       | ficklepickle wrote:
       | This is a solved problem with Nuxt/Vue and the fetch hook. Client
       | side, server side, no problem.
       | 
       | One of the many reasons I love nuxt/Vue.
        
       | whalesalad wrote:
       | This post is hard to digest - it is a rant on 10 different
       | things. All are valid hurdles but I don't see how we can just tie
       | it all up in a bag and call it "data fetching".
       | 
       | Architectures are what help solve these sorts of problems - not
       | tools or libraries. Placing the blame on tools means the real
       | issue has not been identified.
        
       | swiley wrote:
       | You can serialize pretty complex graphs of data and UI
       | information in a new format called "HTML." The software capable
       | of consuming this format is able to merge fragments of it into
       | something called a DOM.
       | 
       | If you're doing something more complex than this in your app then
       | quit whining about browsers not being convenient for you to
       | abuse. The users don't want your crap any more than browser
       | implementers do.
        
       | philplckthun wrote:
       | Not to toot our own horn, but while this mentions GraphQL with
       | Relay / Apollo as fetching clients, with urql and its normalised
       | cache Graphcache we started approaching more of these problems.
       | 
       | Solving the mentioned problems in the article for best practices
       | around fragments is on our near future roadmap, but there are
       | some other points here that we've worked on that especially
       | Apollo did not (yet)
       | 
       | Request batching is in my humble opinion not quite needed with
       | GraphQL and especially with HTTP/2 and edge caching via persisted
       | queries, however we have stronger guarantees around commutative
       | application of responses from the server.
       | 
       | We also have optimistic updates and a lot of intuitive safe
       | guards around how these and other updates are applied to all
       | normalised data. They're applied in a pre-determined order and
       | optimistic updates are applied in such a way that the
       | optimistic/temporary data can never be mixed with "permanent"
       | data in the cache. It also prevents races by queueing up queries
       | that would otherwise overwrite optimistic data accidentally and
       | defers them up until all optimistic updates are completed, which
       | will all settle in a single batch, rather than one by one.
       | 
       | I find this article really interesting since it seems to
       | summarise a lot of the efforts that we've also identified as
       | "weaknesses" in normalised caching and GraphQL data fetching, and
       | common problems that come up during development with data
       | fetching clients that aren't aware of these issues.
       | 
       | Together with React and their (still experimental / upcoming)
       | Suspense API it's actually rather easy to build consistent
       | loading experiences as well. The same goes for Vue 3's Suspense
       | boundaries too.
       | 
       | Edit: Also this all being said, in most cases Relay actually also
       | does a great job on most of the criticism that the author lays
       | out here, so if the only complaint that a reader here picks up
       | are the DX around fragments and nothing else applies this once
       | again shows how solid Relay can be as well.
        
       | iskin wrote:
       | Completely agree! I believe that op-log sync with CRDT-based
       | atomic operations are a better solution.
       | 
       | Logux is one of the example of this approach:
       | 
       | https://logux.io/
        
       | super_hhh wrote:
       | Vue > React
        
         | viviansolide wrote:
         | Suspense feature is great.
        
       | lexicality wrote:
       | > You shouldn't have to ship kilobytes of metadata describing
       | your data schema to clients in order to fetch data.
       | 
       | I feel like this requirement makes every other requirement
       | impossible unless you use some kind of compiled language feature
       | and even then you're not going to be able to have type safety
       | without some kind of metadata.
       | 
       | Also, I don't think it's possible to make any one library that
       | solves all "data fetching" scenarios. How could you reasonably
       | live data (eg stock ticker), enormous data sets (eg looking
       | through individual analytics events) slow but largely static
       | lookups (eg searching a library catalog) and fast but uncachable
       | (eg a SPA forum) into the same API without making it horrendous?
        
         | lexicality wrote:
         | That said, we do need some better standards. I look after a
         | bunch of API integrations at work and we have everything from
         | SOAP to GraphQL to downloading a magically named .xml.gzip file
         | in a FTP directory with at least 10 other homemade REST
         | implementation between and every single one of them is
         | basically returning the same info but in wildly incompatible
         | ways.
         | 
         | At least the SOAP one crashes when they change the API without
         | telling us :/
        
       | asiando wrote:
       | This applies to everything in the browser honestly. Why can't I
       | bind a variable to the DOM natively? I want the variable X to
       | match the value of <input> and vice versa without having to set
       | up a bunch of listeners and hope they don't go in a loop.
        
       | benlivengood wrote:
       | Safe client-side SQL sounds like what the author wants.
       | 
       | * Consistency when fetching data: define a UI that matches a
       | particular SQL view.
       | 
       | * Request batching: It's probably not hard to send deltas on a
       | large view with server-side support for sessions.
       | 
       | * Avoiding network waterfalls: basically the definition of a SQL
       | view, with some session management to de-duplicate traffic when
       | updating the view. A lot of clients support batching queries.
       | 
       | * UX when fetching data: this seems entirely like an oversite of
       | some UI packages, but when all the other points line up there are
       | very distinct points in application flow when the UI will know a
       | query and potential update is in progress.
       | 
       | * Colocation: the definition of a view is necessarily local.
       | 
       | * File size: SQL is pretty lightweight on the schema details in
       | results
       | 
       | * Type safety: SQL doesn't support dependent types, but e.g.
       | postgres is pretty type-y
       | 
       | * Versioning: no explicit support in SQL but for changes to the
       | UI a new view can be created. For changes to the data model a
       | compatible change to the view can be committed in the same
       | transaction as the data model change.
       | 
       | * Realtime updates: the glaring hole in the glory of SQL. You'll
       | have to do some user-defined triggers server-side to support
       | this.
       | 
       | * Consistency when updating data: the relational model with
       | constraints enforces this
       | 
       | * Optimistic updates: if the theoretical differential view update
       | described above exists then this is pretty trivial. Compare local
       | and remote deltas when refreshing the view and indicate to the
       | user the expected state that wasn't committed.
       | 
       | * Request queueing: this one seems to be more of a data model
       | problem. If the data model approximates a state machine and
       | queries are on transitions then yes, they need to be serialized.
       | But why not do complex updates all at once with a multi-statement
       | update transaction that commits or fails atomically?
       | 
       | * UX when updating data: presumably a UI tied to a single view is
       | easier to indicate busy-ness for. If an update transaction is in
       | flight, display a spinner. When it fails or commits display an OK
       | or error.
       | 
       | * Durability when updating data: this could almost certainly be
       | improved for most sql clients. However, idempotence is definitely
       | covered by conditional update transactions.
       | 
       | * Type safety: user defined types if necessary but constraints
       | are where a lot of the type-safety happens in SQL.
       | 
       | * Versioning: backward-compatibility by updating mutable views in
       | the same transaction as data model changes. Forward-compatibility
       | by rendering directly from the view that's returned, not
       | expecting any particular view.
        
       | kabes wrote:
       | Meteor actually seems to come pretty close of you're ok with
       | mongodb
        
       | tyingq wrote:
       | I didn't see "show download progress" as one of the needs. I
       | remember seeing complaints about the fetch api not exposing an
       | easy way to do that. Issues like this one seem to remain:
       | https://github.com/AnthumChris/fetch-progress-indicators/iss...
        
       | rektide wrote:
       | > Realtime updates. Sometimes, you want data to be pushed, not
       | pulled (eg. for things like notifications). But the APIs for
       | pushing and pulling data are often different, both on the client
       | and on the server.
       | 
       | Two and a half months since Google announced the removal of HTTP
       | Push[1]. There'd been a number of threads open (some 5 years old
       | now) asking the Fetch spec to please include some way to allow
       | the page to be notified of Push[2], which would have made HTTP
       | Push super interesting & useful.
       | 
       | After 5 years, we never got anywhere, never got any help from
       | standards body/google in trying to get Push useful. The topic
       | came up a couple times when Abort was being worked on, and it
       | seemed like maybe we'd see some progress, but those finer points
       | got drowned among the noise of the Abort work.
       | 
       | And then Google announced we developers weren't using Push
       | enough, & that they were going to drop it. Without ever having
       | tried to make it useful in the first place.
       | 
       | HTTP/2 seemed to have such promise, was such elation finally
       | getting released in 2015. Seeing so much promise go unfulfilled &
       | then get cancelled has been quite dark. Unlike so so many of the
       | alternatives that we are up to for data fetching, this path was
       | both realtime & still http/resource centric. It still felt like
       | core web architecture, in a way few others do. The unfulfilment
       | of this destiny, this loss, has been jarring, & continues to
       | leave us with these open quandries of what new entirely different
       | alternatives do we invent, over WebSockets, over SSE, over
       | WebTransport, &c. HTTP (almost) was here.
       | 
       | [1] https://news.ycombinator.com/item?id=25064855
       | 
       | [2] https://github.com/whatwg/fetch/issues/51
       | 
       | Edit: there was a deleted comment saying that this kind of use
       | case is not what Push was for, is not there to send unprompted
       | data. Technically, Push can only be done in reply to a http
       | request, so there is a factual limitation. Web Push Protocol gets
       | around this by holding a GET open, to allow "unprompted" data. I
       | think a sizable amount of engineers at the time were indeed
       | thinking of Push as an optimization, a way to get pages to load
       | faster. But this contingent of folks who saw HTTP/2 Push enabling
       | pushing data capabilities, who were hungry for it, who counted on
       | it's maturation: I think they had reasonable expectations, and
       | that we're in a very weird place on the web, with HTTP
       | technically having the ability to push semi-unprompted, but
       | browsers never delivering that capability that's now inbuilt in
       | HTTP.
       | 
       | Using Push is still possible for so called unprompted updates
       | even! At least it was till Push got removed. The trick is that
       | the server needed some way to tell the browser which resources to
       | send: so the server might be pushing resources, then using SSE to
       | notify the page of those updates, for ex.
        
         | jkarneges wrote:
         | > this path was both realtime & still http/resource centric
         | 
         | There's always long-polling. :) Not quite as efficient as
         | Server Push, but the logical behavior is similar in that the
         | server pushes an HTTP resource at the client.
        
         | [deleted]
        
       | irrational wrote:
       | > UI frameworks (at this point, React has won)
       | 
       | Isn't this like someone in 2011 saying "UI frameworks (at this
       | point, jQuery has won)"? I think things like Svelte and other up
       | and coming UI frameworks are still being developed because we all
       | recognize that React is not the ultimate UI Framework. Perhaps we
       | will never get there, but surely we can do better than where we
       | are at.
        
         | deergomoo wrote:
         | This is highly subjective of course, but I think Vue has
         | already surpassed React from a technical and ease-of-use
         | standpoint.
         | 
         | Where React still leads handsomely is tooling (the official VS
         | Code Vue plug-in is buggy as all hell), breadth of ecosystem,
         | and employability.
        
       | joverholt wrote:
       | Ember.js seems to check off a lot of those boxes, if you are
       | willing to use a complete solution and not do the 'pick and
       | choose' method of react and friends. While it has lost popularity
       | in the last few years, it has been moving forward technically. It
       | has become leaner and meaner.
       | 
       | Really learning the "Ember Way" to do things can reduce some of
       | the friction the author mentions.
       | 
       | Ember Data can allow you to talk to multiple api backends
       | (differing schemas) while presenting the same model to your UI.
       | If you use the default JsonApi[0] based backend, you get a lot of
       | things for free: powerful filtering, side loading data
       | (relationships), consistent error handling. Sometimes it can be
       | chatty, but that's a spot where HTTP2 can help.
       | 
       | Use ember-concurrency add-on and you have a nice way to manage
       | your requests, things like de-bouncing, handling loading
       | spinners, etc.
       | 
       | [0]https://jsonapi.org/format/
        
         | orf wrote:
         | Seconded, it even handles batching for you.
        
         | Nextgrid wrote:
         | I'm saddened to see that almost a decade after Ember's release,
         | the front-end world still insists rolling their own (terrible)
         | reimplementation of it.
         | 
         | I would've expected that a decade later we would've settled on
         | an Ember-like framework for the front-end and moved beyond
         | constructing URLs and parsing JSON responses manually but
         | apparently not.
        
           | whalesalad wrote:
           | The rest of the world moved on from Ember because Ember is a
           | pain in the ass to use.
        
             | enspandi wrote:
             | It has improved a lot though - checkout ember octane
        
             | Nextgrid wrote:
             | As someone who's not a front-end developer, but who works
             | near them and sees the (React) code they produce and their
             | general productivity (or lack thereof), what's so bad about
             | it?
             | 
             | To me as a backend developer just reading Ember's docs, it
             | seems like Ember provides most of the conveniences I take
             | for granted in a backend web framework such as Django,
             | Rails or Laravel.
             | 
             | On the other hand, the front-end code I see from the people
             | I work with seems to have no standard for structure (every
             | project has its own), reinvents the wheel all the time
             | (using Axios and building the URLs manually with string
             | concatenation for example), etc. Most of the stuff they do
             | (and redo) from scratch seems like something that would be
             | handled by Ember to begin with.
             | 
             | So what's so bad? I feel like (as an outsider - feel free
             | to prove me wrong) Ember is fine for most purposes, and
             | edge-cases where React or alternative approaches do provide
             | a benefit can be used ad-hoc without having to use it for
             | your _entire_ application.
        
       | gajus wrote:
       | Relay modern does all of the things that this article sets as a
       | criteria for good data fetching.
        
         | bcherny wrote:
         | I'd agree Relay is relatively far along, compared to other
         | frameworks.
         | 
         | I might lump its support into a few groups:
         | 
         | - Full (eg. request batching)
         | 
         | - Full, but painful (eg. colocation)
         | 
         | - Partial (eg. mutation queuing)
         | 
         | - Non-existent (eg. durability guarantees)
         | 
         | (I've been using Relay Modern daily for a few years.)
        
         | ch4s3 wrote:
         | It doesn't have a great story around error handling IMHO.
        
           | orta wrote:
           | I've found Relay to be pretty solid with error handling,
           | though I think the ability in how to handle GraphQL errors
           | does hurt Relay here, but it does for all GraphQL clients.
           | 
           | Re: parent, I also was surprised to see Relay dismissed on
           | the list, it solves every problem they bring up in the list,
           | perhaps maybe not the real-time aspects
        
             | ch4s3 wrote:
             | I should have clarified that Relay flavored GraphQL from a
             | backend perspective is lacking in this respect.
             | 
             | Yeah, I think relay is pretty good, but I'm not sure the
             | broader ecosystem is really there yet. Outside of node, the
             | backend libraries aren't really fully baked yet, and the
             | standard seems to have some holes. But I'm somewhat
             | optimistic.
        
       | robertoandred wrote:
       | SWR or react-query?
        
         | dsego wrote:
         | I've used swr, but they seem very similar. Very easy to use for
         | server synced state imho. Try both and pick the one that feels
         | nicer to you.
        
         | dinkleberg wrote:
         | I started my current project using SWR and then switched to
         | react-query after dealing with some annoyances with SWR.
         | 
         | Overall react-query is impressive for data fetching, but I've
         | run into issues with mutations and cache invalidation.
        
           | AgentME wrote:
           | I've been disappointed at how SWR and react-query seem to
           | only support the bare minimum for mutations. As far as I can
           | tell, they don't offer any kind of protection from refreshes
           | overwriting any local mutations that haven't been saved to
           | the server yet. They don't do any handling around updating
           | the data on the server, so you need to handle issues yourself
           | like retrying, deciding when to send to the server, and
           | making sure you never have overlapping update requests racing
           | each other. I've had trouble finding any library in the React
           | or general JS ecosystem that handles this stuff.
        
           | shuding wrote:
           | Hey! SWR author here. Mind sharing the annoyances and how I
           | can make it better for you?
        
       | heipei wrote:
       | This post feels like a uninformed and undifferentiated rant
       | against "things are too complex". Let's start with the first
       | paragraph: What does the JavaScript fetch API have to do with
       | data management? How can you compare the fetch() API with Swagger
       | (an API documentation format) with Protobuf (a serialisation
       | format)? That doesn't even make sense.
       | 
       | Second paragraph: "The UI should automatically update everywhere
       | the data is used". Again, what does this have to do with any of
       | the above? That is state management, yeah, and you can build
       | proper state management with any HTTP library and any message
       | serialisation format.
       | 
       | Request batching: How would that happen "automatically"? By
       | waiting to fire requests and then batching them?
       | 
       | UX when fetching data: What does that have to do with any of the
       | above? You still have to decide how your UI displays the fact
       | that a piece of data is loading. What do you expect there to be
       | in place? Best thing I could imagine is to have a global
       | operations indicators a la Adobe Lightroom which tells you how
       | many HTTP requests are in flight.
       | 
       | I could go on, but the last paragraphs maybe highlights the lack
       | of understanding the author had: "UI Frameworks (at this point,
       | React has won)". If React had "won" then why would we be having
       | this discussion. React hasn't "won" because it solves one piece
       | of the puzzle: Rendering. For every little other thing you have
       | to incorporate another library or figure out your own solution:
       | Routing, State Management, CRUD / HTTP API, etc. If anything,
       | Ember.js would most closely fit the bill of incorporating most of
       | the things the author seems to care about yet can't articulate
       | clearly.
        
         | dillondoyle wrote:
         | I might intuit that 'request batching' could be benefit http/2
         | but probably not what they were thinking about. And you'd have
         | to have a lot of simultaneous http requests for it to help at
         | all.
         | 
         | But I'm with you on trying to batch this with your JS should
         | not be a browser thing or even a built in standard library JS
         | function.
         | 
         | One could do it themselves - maybe graphQl kind of this idea of
         | more complex queries + maybe just throw the requests you want
         | to make into an array and when it hits length = 5 send them all
         | at once. But I don't see how that would help response times at
         | all.
        
         | batoure wrote:
         | What this person said! ^
         | 
         | almost all of the mentioned issues have solutions out their but
         | the author is jumping around the stack with no sense of true
         | purpose. How does graphql impact your SPA updating views, it
         | doesn't..
        
         | pferdone wrote:
         | Half of the stuff he mentioned are covered by apollo-graphql
         | and libs in that eco-system: query batching, notifications (via
         | subscriptions), automatic state updates via cache, typesafety
         | with typescript and grapqhl-codegen. It doesn't seem like he
         | even looked at the libraries he listed. :(
        
           | bcherny wrote:
           | Sorry if it was unclear, but my argument is that while many
           | libraries solve pieces of the problem, no one library (or
           | standard) solves all, or even most, of these.
        
           | mewpmewp2 wrote:
           | Yeah, exactly, half of the stuff. You should be able to have
           | all of this available by default. And it should have first
           | class support without having to do complex setup. Also
           | writing gql queries has always felt hacky and uncomfortable
           | to me, without IDEs having the best support for it, and type
           | safety? But maybe I haven't had the perfect setup.
           | 
           | Also graphql forces you to a certain way to resolve your data
           | which may not always be the best fit.
        
         | lxe wrote:
         | I actually think the problems outlined are pretty valid.
         | 
         | Yeah, there are solutions to them, but I think what the author
         | is saying is that you have to subscribe to something batteries-
         | included, like Meteor, or otherwise implement the solutions
         | yourself from bits and pieces.
        
           | derefr wrote:
           | "You have to subscribe to something batteries-included, like
           | Meteor, or otherwise implement the solutions yourself from
           | bits and pieces."
           | 
           | ...yes; that is, in fact, the conceptual dichotomy in
           | solutions to essentially-complex problems. Either someone
           | else solves them for you, or you have to solve them yourself.
           | 
           | I mean, yes, there is a part of the solution-space in-between
           | these two extremes -- a point where there's a batteries-
           | included thing that someone else built but then _gives away
           | for free_ , perhaps as an open-source project you just have
           | to run on your own infra. So it's mostly solved for you, and
           | then you just do a little bit to "get the solution running"
           | for your use-case. _That_ point in solution-space is
           | conspicuously absent for web data sync.
           | 
           | But, in domains with essential complexity, that middle-ground
           | part of the solution-space is _usually_ conspicuously absent.
           | Because it takes continuous dedicated effort (i.e. labor;
           | capital expenditure) to solve the complex problem in a
           | cleanly-abstracted way. And it 's very rare that anyone's
           | going to go to the effort, unless they expect a return on
           | their labor investment (by e.g. keeping the solution
           | proprietary, and building a SaaS business around it.)
        
         | bcherny wrote:
         | Author here.
         | 
         | Data fetching, caching, consistency, and UX are all closely
         | related. If you treat them as separate problems, you're punting
         | the problem onto product engineers, who won't solve it well.
         | (See the last paragraph of the post, which suggests this same
         | idea.)
         | 
         | > That is state management, yeah, and you can build proper
         | state management with any HTTP library and any message
         | serialisation format.
         | 
         | You're right that to do this _manually_ it 's just state
         | management. But to _automatically_ update the UI, it means your
         | client data layer (eg. Apollo) needs to know  & track the
         | identity of fields; the data layer also needs to be able to
         | subscribe to fetches anywhere in your app, not local fetches;
         | it also means your protocol needs to support this identity (via
         | agreed-upon ID fields); etc. These problems are all closely
         | related.
         | 
         | > Request batching: How would that happen "automatically"? By
         | waiting to fire requests and then batching them?
         | 
         | eg. Relay does this by statically combining requests throughout
         | a React tree into a single request at the top of the tree. You
         | could also do it dynamically, as you suggest. The tradeoff is
         | often performance.
         | 
         | > UX when fetching data
         | 
         | Having engineers manually define loading states doesn't scale.
         | React is approaching this problem with Suspense, and you could
         | imagine standard loading states when fetches are in flight.
        
         | Garlef wrote:
         | I think the post is a bit unfortunate in its wording and this
         | seems to have sent you off on a wrong track.
         | 
         | From how I read it, this the post is not specifically about JS
         | and a discussion of the specific technologies mentioned but
         | rather concerned with the following very general situation:
         | 
         | 1. There's a user sitting in front of a browser.
         | 
         | 2. There's a backend server providing data and points of
         | interaction with that data.
         | 
         | I think the central point of the post now is that we don't have
         | a satisfying technical solution for this situation.
         | 
         | Let's take a look at one of the points you mentioned. Maybe you
         | might find there's actually some valid points in the post and
         | give it a more favourable reread.
         | 
         | > UX when fetching data: What does that have to do with any of
         | the above?
         | 
         | Here, the author of the post writes: _" It's a big burden for
         | engineers to have to manually add loading spinners and error
         | states, and engineers often forget."_
         | 
         | I think it's more or less clear how you could implement this
         | using only plain vanilla js. Cumbersome but doable: A very
         | manual, imperative process.
         | 
         | Now let's envision a technology from a possible future:
         | const twitterFeed =
         | createMagicDataSource("https://twitter.com/...")
         | const feedComponent = magicRendererComponent(twitterFeed, state
         | => /* HTML like declarative description of the visuals */)
         | 
         | Imagine this was everything you had write in your code to get
         | the following:
         | 
         | * state gets automatically loaded when the first instance of
         | the component is created
         | 
         | * updates are automatically visualized in the client based on
         | the internals of the declaration in the renderer
         | 
         | * you don't have to specify if the updates are done by polling,
         | websockets or whatever: the two magic methods figure this out
         | by themselves.
         | 
         | * you don't have to specify how the data is fetched in the
         | first place. giving the a URI to the `createMagicDataSource`
         | function is enough.
         | 
         | * additional instances of the component don't fetch the data
         | again
         | 
         | * updates are efficient: the sync method only exchanges exactly
         | the data required, only the minimal visual updates are
         | performed
         | 
         | * marking feeds as "seen" by the user is also done by magic and
         | syncs across devices (same for other non-ephemeral ui state).
         | 
         | Now: And I'm sure you'd agree that we are not there yet
         | technologically. But I hope you agree that this would be really
         | nice.
        
           | machiaweliczny wrote:
           | Apollo client and Elixir LiveView are solving most of these.
        
             | Garlef wrote:
             | Yes. But do they automagically create and maintain database
             | indexes for the most common requests made by your
             | webclients?
        
               | ricketycricket wrote:
               | LiveView doesn't allow arbitrary queries (or any queries
               | really), so this is a non-issue.
        
           | ivanhoe wrote:
           | > But I hope you agree that this would be really nice.
           | 
           | Black boxes with tons of magic are great if you need to do
           | exactly that one thing that creators had in mind. When you
           | need it to work a little bit different you're usually either
           | just out of luck, or the added flexibility makes whole api
           | very complex (and usually buggy, as it goes hand in hand).
           | It's just super hard to make things very high-level and
           | simple, while still flexible enough.
           | 
           | Having a number of simpler functionalities that you're free
           | to compose any way you like is for me preferred approach
           | anytime. Most of the things that you mention can be solved
           | with fairly simple wrapper libs doing just one thing
           | (tracking state of connection, tracking errors, batching
           | requests, etc.). Perhaps not in a perfectly reusable way, but
           | good enough to allow easy recycling from project to project,
           | and it's way easier to use and debug and adjust than if we
           | had one huge built-in service object to handle it all.
        
           | mewpmewp2 wrote:
           | I think parent is completely missing the point. In my opinion
           | the way it should be is that in the backend you export a
           | typed function like "getTasks(filter: Filter): Tasks
           | 
           | And in the frontend component you should be able to use it
           | immediately and it would be correctly typed without having to
           | duplicate types or anything. And if function is not complete
           | yet it will not render the component before.
           | 
           | This should be instead of REST and Graphql, both of which
           | have many issues imo.
        
         | whateveracct wrote:
         | > Request batching: How would that happen "automatically"? By
         | waiting to fire requests and then batching them?
         | 
         | Haxl is good prior art for automatic batching and concurrency.
         | But it helps that Haskell makes the "when" very explicit thanks
         | to its type system.
         | 
         | https://engineering.fb.com/2014/06/10/web/open-sourcing-haxl...
        
       ___________________________________________________________________
       (page generated 2021-01-27 23:01 UTC)