Articles

Streaming capabilities comes to zlFetch

Published on:

Just last weekend, I sat down and gave zlFetch another brand new update β€” streaming capabilities. With v6.2.0, zlFetch is now able to:

  • Receive and convert streams automatically (without you having to write a stream decoder manually)
  • Have Typescript support (thanks to juji).

Now zlFetch is now prime for handling AI-related streamsπŸ˜‰.

What is zlFetch?

It's a library I've created that helps you with the Fetch API. It provides a ton of quality-of-life improvements like:

  • Automatic response solution (so no need to use response.json)
  • Promise-like error handling
  • Usage with await easily
  • Simple Basic and Token based authentication headers
  • And a ton of other things

Just my personal opinion:

  • It's better than axios cos it's less complicated
  • It's better than ky cos it has better defaults

Three Types of Streams

As far as I know, there are three types of streams:

  1. Server Sent Events (SSE)
  2. Chunked Encoding
  3. A normal stream

Server Sent Events lets you create a connection between a browser and the server. If the connection is dropped, the browser can automatically connect (with the help of Event Source). This happens if the server sets Content-Type: text/event-stream.

Chunked Encoding lets one server tell another that they're going to send data in bits. The receiving server is supposed to receive everything, combine them, before sending letting the clients use them. This happens if the sending server sets the Transfer-Encoding: Chunked header.

Normal Streams happens when the sending server doesn't send over a Content-Length property.

zlFetch detects all three kinds of streams and decodes them for you automatically, so you can just loop through the response body to get your data β€” no need for manual decoding!

Oh, by the way, if the chunk contains JSON data, zlFetch converts that into a JavaScript object for you automatically. Again, quality of life improvements β€” so you can build stuff without having to deal with boilerplate!

// Basic Stream Handling Example with Fetch
const response = await fetch('some-url')
const reader = response.body.getReader()
const decoder = new TextDecoder()

while (true) {
  const { done, value } = await reader.read()
  buffer += decoder.decode(value, { stream: true })

  // Decode the chunk
  let chunk = typeof value === 'string' 
    ? value 
    : decoder.decode(value, { stream: true })

  chunk = chunk.trim()

  try {
    chunk = JSON.parse(chunk)
  } catch (error) {}

  // FINALLY, you do something with your chunk 🫠
}
// With zlFetch 
const response = await zlFetch('some-url')

for await (const chunk of response.body) {
  // Do something with your chunk πŸ˜„
}

Even for chunked encoding, you can actually receive the data in your browser as chunks! To make that happen, we can't parse the stream in advance inside zlFetch. But we've given you a readStream helper to, you know, deal with the stream decoding stuff.

import zlFetch, { readStream } from 'zl-fetch'

// Decoding chunked encoding as streams in the browser
const response = await zlFetch('some-url')

// Just add this helper 
const stream = readStream(response)

for await (const chunk of stream) {
  // Then do something with your chunk πŸ˜„
}

Text Event Stream and Server Sent Events

Server Sent Events is a pretty cool technology. It's similar to Fetch, but made for streams β€” because your browser can reconnect to the server if you get disconnected!

The best way to consume Server Sent Events is through the Event Source API. We've made that simpler too with zlEventSource.

I'd leave further explanation for a future article. If you're interested, you can check out the docs right now πŸ˜‰.

Making sense of starting-style

Published on:

@starting-style is a CSS at-rule that allows you to create transitions for elements that are hidden by display:none.

It's one of those things that seems simple on first glance, but turns out to be quite complex. The main reason is because we can't DRY (Don't Repeat Yourself) when using @starting-style β€” you have to specify certain styles twice.

Making sense of starting style is actually pretty simple. You have to write three selectors:

  1. One for the base state
  2. One for the opened state
  3. One for the starting state

Upcoming Breaking Changes for Splendid Layouts

Published on:

I acknowledge the irony that I'm announcing breaking changes just after ranting about breaking changes.

But, I believe it's important to let you know about breaking changes in advance so you can ease into the new library as much as possible.

Killing and Restarting pm2

Published on:

I encountered a strange error with pm2 that has the following properties:

  1. pm2 list displays nothing even though processes should be running
  2. After restarting a couple of projects, pm2 list still displays nothing
  3. Running pm2 list hogs the server and creates a spike (see picture below).

Understanding Recursion in JavaScript

Published on:

Recursion happens when a function calls itself over and over.

A function that calls itself over and over is called a recursive function. Here's an example of a recursive function:

function helloWorld() {
  console.log('Hello world')
  helloWorld()
}

(Don't try this code because your browser would hang). I'll explain how you write a proper recursive function and why you may want to use one.

Best Practice for Astro Endpoints

Published on:

Astro strips away query parameters from endpoints if you're in a static rendering mode. So, unless you're using SSR for all your pages, you'll need to ensure that your endpoints are not pre-rendered.

What developers should be learning

Published on:

Many developers are learning frameworks and algorithms to keep up with trends β€” so they can continue to be employable.

That's one way of looking at things. But I propose another approach.

A Great Failed Experiment

Published on:

Couple of years ago (I forgot exactly when), I removed the dates that were preceeding the file names of my blog articles.

Data Table Accessibility in 2024

Published on:

A comment from Estelle Weyl sparked this whole article.

> I know the display property would override the native semantics of a table, like setting display: grid, but I am not sure if that is still the case."

(Emphasis mine).

This prompted me to do some research.

Found the Light

Published on:

After about a year (or two) of paralysis, I finally know how to move forward with Magical Dev School β€” particularly how I create courses and content.

Understanding and using npm exports

Published on:

npm exports lets you specify how users can import or require your files. (For instructions on using require, see below).

Invisible adversaries

Published on:

In Bravery, I mentioned I had a few fears.

These fears are real to me. They don't feel like the bogeyman that Seth Godin mentions in the Practice. If they are, perhaps I haven’t summoned enough courage to look them in the eye, enough to a point that they disappear, yet.