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.
-
First item: Fastify v5 is out!
- Drops support for Node.js v18 and earlier.
- Consolidates the removal of numerous deprecated APIs.
- Migration guide — some easy to miss details in there!
- Covered in this video by Matteo Collina.
-
A TC39 proposal for an Error Safe Assignment Operator.
- From Arthur Fiorette, author of Kita.
- Mimicks Go's explicit error handling to some extent.
- A lot of support in the community but very unlikely to ship.
- Covered in this video by @t3dotgg.
-
- From Natalia Venditto, Michael Dawson, Matteo Collina and James Snell.
- A set of principles for building robust Node.js systems.
- Covered in this video by Platformatic.
-
- From Google Engineer Philip Walton.
- Highlights the dangers of Babel ES5 transpilation.
- Most sites ship ES5 code that don't even work in IE11.
- Includes a comprehensive overview of the state of build tools.
- Covered in this video by @ThePrimeTimeagen.
-
Remix's concurrent submissions are fundamentally flawed
- From José Valim of Elixir fame.
- Analysis uncovering issues with Remix's submit and revalidate model.
- My takeaway is that WebSockets are superior for this kind of problem.
- Covered in this video by the @ThePrimeTimeagen.
-
- From Matteo Collina with a bit of help from yours truly!
- Vue was the final winner after many iterations.
- Great collaboration with lots of community feedback.
- Covered in this video by @TheAlexLichter.
- Also covered in this video by @ryansolid.
-
- From Nolen Royalty, who also recorded his own video about it.
- Fun implementation using a byte array and Redis to flip values.
- Covered in this video by @t3dotgg.
-
Scheduler.yield availability in Chrome 129 beta.
- Covered in this blog post by Umar Hansa.
- API that allows yielding priority back to the main task queue.
- Equivalent to resolving a promise with
setTimeout(resolve, 0)
. - Apparently also available in Node since v16.4.0.
- Covered in this video by @t3dotgg.
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.
-
The Solid Metadata & JSX Head Tags RFC
- From Ryan Carniato.
- Also check out earlier document exploring metadata APIs for Solid.
- Analysis: how modern frameworks handle
<head>
elements. - Covered in this video also by Ryan
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.