Live data from Hacker News

Progressive JSON

overreacted.io

161–170 of 244 posts

Re: Progressive JSON

#161
post #112
post #79

Earlier quoted context omitted.

Doesn't that depend on what you mean by "shave ms loading a page"? If you're optimizing for time to first render, or time to visually complete, then you need to render the page using as little logic as possible - sending an empty skeleton that then gets hydrated with user data over APIs is fastest for a user's perception of loading speed. If you want to speed up time to first input or time to interactive you need to…

> sending an empty skeleton that then gets hydrated with user data over APIs is fastest for a user's perception of loading speed This is often repeated, but my own experience is the opposite: when I see a bunch of skeleton loaders on a page, I generally expect to be in for a bad experience, because the site is probably going to be slow and janky and cause problems. And the more the of the site is being skeleton-loade…

It also breaks a bunch of optimizations that browsers have implemented over the years. Compare how back/forward history buttons work on reddit vs server side rendered pages.

Re: Progressive JSON

#162

People put so much effort into streaming Json parsing whereas we have a format called Yaml which takes up less characters on the wire and happens to work incrementally out of the box meaning that you can reparse the stream as it's coming in without having to actually do any incremental parsing

If we're talking about niche data protocols, edn is hard to beat. Real dates and timestamps and comments, namespaced symbols, tagged elements, oh my!

https://github.com/edn-format/edn

Re: Progressive JSON

#163
post #77

I have seen Dan's "2 computers" talk and read some of his recent posts trying to explore RSC and their benefits. Dan is one of the best explainers in React ecosystem but IMO if one has to work this hard to sell/explain a tech there's 2 possibilities 1/ there is no real need of tech 2/ it's a flawed abstraction #2 seems somewhat true because most frontend devs I know still don't "get" RSC. Vercel has been aggressively…

Every use case has its optimal stack. Isomorphic rendering (NextJS, Nuxt, Sveltekit with "non-static" adapters, ...) is a good fit for very few use cases only.

Many "thought leaders" still don't get the math right. At first visit, your Next app can't serve individual content. So you need two round trips. Both are slow as they are typically served from a Node server.

Serving the app (properly built and bundled, e.g. using Astro or a small and fast SPA like Solid or Svelte) from a CDN and the data from an API is faster at first visit.

At consecutive visits the Next app can serve the rendered page with individual content. Nice and fast. But the CDN hosted app is still in the browser cache. It's even faster! So also just one request to the backend for the individual data is needed.

Regarding SEO the arguments for isomorphic rendering are also flawed. If you care about SEO, just create static html (again, Astro makes it very easy) and put it on a CDN. Why should a crawler care about individual content, that isomorphic frameworks can provide? For SEO the response of a anonymous request matters. So just the static content.

IMO 99% of the use cases are better solved with traditional server rendered MPAs (e.g. Django or ASP.NET MVC), fast SPAs (not React, but Solid, Svelte or Vue) and if SEO and first paint really matter static sites (e.g. Astro).

Re: Progressive JSON

#164
post #71

The thing I have seem in performance is people trying to shave ms loading a page, while they fetch several mbs and do complex operations in the FE, when in the reality writing a BFF, improving the architecture and leaner APIs would be a more productive solution. We tried to do that with GraphQL, http2,... And arguably failed. Until we can properly evolve web standards we won't be able to fix the main issue. Novel fra…

RSC, which is described at the end of this post, is essentially a BFF (with the API logic componentized). Here’s my long post on this topic: https://overreacted.io/jsx-over-the-wire/ (see BFF midway in the first section).

But with a considerable amount of added complexity and bulk. And operational drawbacks. A well designed API (Go, ASP.NET, Java) and a fast SPA (let's say Solid) without client side global data management, just per component data fetching, are simple and fast. You can use a CDN to cache not only the app but the data.

Re: Progressive JSON

#165

I understand the GraphQL has fallen out of favour somewhat, but wasn’t it intended to solve for this?

It can't fall out of favor if it was never really in favor to begin with. GraphQL was a quite brief hype then a big technical debt.

Interesting take considering graphql adoption is growing and generally in favor at my company.

Re: Progressive JSON

#166
There are at least two other alternatives I'd reach for before this.

Probably the simplest one is to refactor the JSON to not be one large object. A lot of "one large objects" have the form {"something": "some small data", "something_else": "some other small data", results: [vast quantities of identically-structured objects]}. In this case you can refactor this to use JSON lines. You send the "small data" header bits as a single object. Ideally this incorporates a count of how many other objects are coming, if you can know that. Then you send each of the vast quantity of identically-structed objects as one-line each. Each of them may have to be parsed in one shot but many times each individual one is below the size of a single packet, at which point streamed parsing is of dubious helpfulness anyhow.

This can also be applied recursively if the objects are then themselves large, though that starts to break the simplicity of the scheme down.

The other thing you can consider is guaranteeing order of attributes going out. JSON attributes are unordered, and it's important to understand that when no guarantees are made you don't have them, but nothing stops you from specifying an API in which you, the server, guarantee that the keys will be in some order useful for progressive parsing. (I would always shy away from specifying incoming parameter order from clients, though.) In the case of the above, you can guarantee that the big array of results comes at the end, so a progressive parser can be used and you will guarantee that all the "header"-type values come out before the "body".

Of course, in the case of a truly large pile of structured data, this won't work. I'm not pitching this as The Solution To All Problems. It's just a couple of tools you can use to solve what is probably the most common case of very large JSON documents. And both of these are a lot simpler than any promise-based approach.

Re: Progressive JSON

#167

> I’d like to challenge more tools to adopt progressive streaming of data. It's a solved problem. Use HTTP/2 and keep the connection open. You now have effectively a stream. Get the top-level response: { header: "/posts/1/header", post: "/posts/1/body", footer: "/posts/1/footer" } Now reuse the same connection to request the nested data, which can all have more nested links in them, and so on.

> Now reuse the same connection to request the nested data, which can all have more nested links in them, and so on. This still involves multiple round-trips though. The approach laid out in the article lets you request exactly the data you need up-front and the server streams it in as it becomes available, e.g. cached data first, then data from the DB, then data from other services, etc.

When you have an HTTP/2 connection already open a 'round-trip' is not really a gigantic concern performance-wise. And it gives the client application complete control and ver what nested parts it wants to get and in what order. Remember that the article said it's up to the server what order to stream the parts? That might not necessarily be a good idea on the client side though. It would probably be better for the client to decide what it wants and when. Eg, it can request the header and footer, then swap in a skeleton facade in the main content area, then load the body and swap it in when loaded.

Re: Progressive JSON

#168

Does this scheme give a way to progressively load slices of an array? What I want is something like this: ["foo", "bar", "$1"] And then we can consume this by resolving the Promise for $1 and splatting it into the array (sort of). The Promise might resolve to this: ["baz", "gar", "$2"] And so on. And then a higher level is just iterating the array, and doesn't have to think about the promise. Like a Python generator…

From what I understand of the RSC protocol which the post is based on (might be wrong since I haven't looked closely at this part), this is supported: https://github.com/facebook/react/pull/28847.

>The format is a leading row that indicates which type of stream it is. Then a new row with the same ID is emitted for every chunk. Followed by either an error or close row.

Re: Progressive JSON

#169

I don't mean to be dismissive, but haven't we solved this by using different endpoints? There's so many virtues: you avoid head of line blocking; you can implement better filtering (eg "sort comments by most popular"); you can do live updates; you can iterate on the performance of individual objects (caching, etc). --- I broadly see this as the fallout of using a document system as an application platform. Everything…

Sort of! I have two (admittedly long) articles on this topic, comparing how the code tends to evolve with separate endpoints and what the downsides are:

- https://overreacted.io/one-roundtrip-per-navigation/

- https://overreacted.io/jsx-over-the-wire/

The tldr is that endpoints are not very fluid — they kind of become a "public" API contract between two sides. As they proliferate and your code gets more modular, it's easy to hurt performance because it's easy to introduce server/client waterfalls at each endpoint. Coalescing the decisions on the server as a single pass solves that problem and also makes the boundaries much more fluid.

Re: Progressive JSON

#170
post #112

Earlier quoted context omitted.

> sending an empty skeleton that then gets hydrated with user data over APIs is fastest for a user's perception of loading speed This is often repeated, but my own experience is the opposite: when I see a bunch of skeleton loaders on a page, I generally expect to be in for a bad experience, because the site is probably going to be slow and janky and cause problems. And the more the of the site is being skeleton-loade…

It also breaks a bunch of optimizations that browsers have implemented over the years. Compare how back/forward history buttons work on reddit vs server side rendered pages.

It is possible to get those features back, in fairness... but it often requires more work than if you'd just let the browser handle things properly in the first place.
Post reply on HN