Hacker News new | ask | show | jobs
by potatoz2 1506 days ago
This is wrong because you’re not considering the whole picture:

- to turn the JSON into HTML, you not only need the template you mentioned, you also need code to execute that template (potentially lots of it); preact is 10KB ungzipped (other frameworks, like React/Angular/Ember, are way larger), so your HTML solution is already 10,000 characters ahead (by comparison, the markup you demoed is ~90 bytes per book, so you’re ahead until at least ~100 books on the page, without considering the framework, your code, and the following points)

- HTML compresses amazingly well because it’s repetitive so the overhead is less than you think

- HTML stream renders, so you can start rendering the first book immediately; JSON streaming is technically possible, but not built-in, and quite difficult to implement (and it requires even more JS)

- the same KB of JS is way more expensive than it would be as HTML (or images) because parsing, compiling, and executing is slow

- latency is often a larger problem than bandwidth, especially on mobile, so saving bandwidth is less important than (a) streaming and (b) client-side blocking time

- a large number of users visit one page and bounce, for typical websites, so the promised savings once the SPA is live doesn’t materialize

- the naive way to implement a SPA is _full_ of footguns; first of all, you’d naively load the template for all the pages, making the overhead problem even worse, naively you wouldn’t render anything until the JS has arrived, delaying the TTFMP enormously, naively you’d mess up routing, etc.

- it’s relatively trivial to preload/precache HTML pages, including in a service worker to support offline, making performance on par or better than a SPA

I happily work on a huge SPA daily, for context.

1 comments

- about HTTP compression (gzip, brotli) - it works on byte/text level and doesn't know about your markup template repetition (where structure is mostly the same but small changes everywhere) so it will be not as efficient as manual template-data separation

- about SPA - in my comment I said no word about SPA, it's a more complex layer on top. I only arguing about template-data separation approach to decrease data duplication and traffic consumption. And no, you don't need to rewrite your app as SPA and no react/preact/javascript frameworks required. You can use your server-side rendering and just change format of what you are sending to user. Instead of sending index.html with repetitive html markup for every list item you can basically send script-tag where you loop over data and build html-markup directly on a client

<doctype html>

<html>

<body>

   ....

   <div id="books"></div>

   <script>

     const data = [{title: "...", author: "...", description: ""}, {...}]

     document.querySelector("#books").innerHtml = data.map(item=>`

        <div class="book">

           <div class="book-title">${item.title}</div>

           <div class="book-author">${item.author}</div>

           <div class="book-description">${item.description}</div>

        </div>

     `).join(``);

   </script>

 </body>
</html>

Yes, it lacks http streaming but - less repetitive html markup -> smaller size -> less time to download -> http streaming becoming less useful

And again - you can use your favorite http compression (gzip, brotli, etc) on top of this template-data separation approach to compress even more

I’ve just tested what you suggest with a page that contains 20 books (no HTML or JS minification, and probably some typos because I didn’t run it).

https://pastebin.com/8CM1eUKQ the HTML version https://pastebin.com/ujrai58n the templated version

Even I was surprised by the result. The original size is what you’d expect: 5.3K for the full HTML version, 2.4K for the JS template version. Once Brotlied (default compression) however, the situation changes completely: 127 bytes (!) for the pure HTML version and 197 bytes for the template version. This is even true for Gzip, 213 vs 284 bytes.

I don’t know if Brotli (and Gzip) are somehow optimized for HTML, but yeah it really doesn’t make sense to use templates here.