Welcome to the very the first edition of this digest!

At the bottom of this page you'll find links to the main YouTube channels and newsletters I'm subscribed to. I'd love to get more suggestions.

Theo's video also led me this little gem of a video covering the event loop by Lydia Hallie. You should watch that and also Matteo Collina and James Snell's Broken Promises Workshop if you haven't already.

Closing thoughts: a blow to the <head>

Ryan's research came at a rather convenient time to me as I've been researching the very same thing for another upcoming piece. In fact, watching Ryan talk about this for two hours is what prompted me to start this digest in the first place. Some things are just too important to remain buried in a five-hour YouTube video only a few hundred people are going to watch. Blog posts are easier.

I wanted to emphasize a big point in the whole discussion: collecting metadata for the <head> as you allow frontend components to be server-side rendered is an extremely bad idea, as far as Node.js performance is concerned.

This pattern is still currently encouraged by Nuxt, with its useHead() composable from the underlying unhead library. In the latest Next versions we find generateMetadata(), which hints at it being decoupled from the SSR phase, but when you dig through the code, you still see it still appears very much heavily tightly coupled to it and all its RSC gimmicks.

The problem here is that when you make <head> elements dependent on SSR, you're essentially adding the overhead of running whatever framework's SSR API you're using, which includes loading entire components and executing their code before you can deliver the <head> to the client. By doing so, you're mixing two conceptually distinct operations: one is retrieving and sending metadata for the page you're rendering, and another is rendering the content itself.

This is why in @fastify/vue, the delivery of the <head> is completely decoupled from the SSR phase. Each route component can export a getMeta() function, which is executed before any SSR API is even called.

First metadata is collected via route.getMeta() in a preHandler():

async preHandler (req, reply) {
  try {
    if (route.getMeta) {
      req.route.head = await route.getMeta(req.route)
    }

Then it's passed to a Readable generator that will ensure the <head> is streamed right away without having to wait for the whole SSR phase, provided of course you have Vue streaming enabled in this case.

The next version of @fastify/vue — currently being rewritten in TypeScript — will further solidify this behavior and make sure the <head> is streamed instantly even in the case of synchronous SSR.