Valibot and the circle of life

Issue #297.June 13, 2024.2 Minute read.
Bytes

Today’s issue: 10 years of Vue, an epic lawsuit, and a React Compiler cliffhanger that’ll keep you on edge.

Welcome to #297.


Eyeballs logo

The Main Thing

Rafiki holding up Simba

And it moves us all

Valibot and the circle of life

If you’ve followed the JavaScript ecosystem for a while, you’ve probably noticed an interesting pattern: A new library comes in, changes the game, and gets super popular – which locks it in to certain design decisions that come with tradeoffs. Eventually, these tradeoffs create space for a new library to come in and gain popularity by being faster, smaller, more modular, etc. – at least for a while.

We watched this circle of life take place when developers migrated from Underscore to Lodash, from Moment.js to Date-fns, and we could see it again with Valibot, which just released v0.31.0 last week.

Quick review: Valibot is heavily inspired by Zod, a schema validation tool for Typescript that can generate type definitions, validate inputs, and transform data. Zod has grown extremely popular over the last few years, powering tools like Astro’s content collections, and it’s the default tool for tRPC for providing end-to-end type safety over the network. So what makes Valibot different?

Functionally, Valibot is basically the same thing as Zod. It does schema validation, generates type definitions, and can transform data. But internally, it has some key differences:

  • Modular Design: Valibot uses function composition, with each piece of functionality getting its own export instead of chaining, enabling bundlers to tree shake unused code.

  • Improved Flexibility: With this latest version, Valibot added a pipe method that allows you to transform data type within a pipeline without needing a bunch of nested functions.

  • Smaller Bundle Sizes: Depending on the schema, Valibot can be up to 95% smaller than Zod. For validating client-side code like forms and inputs, this can be a big advantage.

Bottom Line: Zod might be too entrenched at this point to give up serious ground, but Valibot is definitely making developers take notice. Only time will tell if this is another Underscore-Lodash situation, or if Zod will prove nimble enough to stay on top of the food chain.

        

Convex logo

Our Friends
(With Benefits)

How it feels building my app's entire backend with TypeScript

Genie from Aladdin talking about his power

Convex is like someone made Firebase in 2024, then combined it with tRPC

That’s because they give you a fully transactional database with no SQL required – plus a modern DX with tRPC-style autocomplete for end-to-end type safety.

It’s truly an all-in-one backend platform that makes it feel like you have superpowers because of how fast you can build. Here’s what else it comes with:

  • First-class support for all your favorite frontend frameworks (see docs)

  • Optimized caching, ACID compliance, and schema enforcement with queries expressed in pure TypeScript code

  • Built-in realtime updates with automatic subscriptions set up on all your queries

Try out their free tier — and just make one decision for your backend.


Spot the Bug logo

Spot the Bug

Sponsored by Snyk

They created this comprehensive guide on reporting AppSec risk to help you prioritize security risks in your workflow and see if your team’s approach is actually working.

<!DOCTYPE html>
<html lang="en">
  <body>
    <h1>Registration Form</h1>
    <form id="myForm">
      <input type="text" id="username" placeholder="Username" />
      <input type="password" id="password" placeholder="Password" />
      <input type="email" id="email" placeholder="Email" />
      <button type="submit" id="submitBtn">Submit</button>
    </form>

    <script>
      document
        .getElementById("myForm")
        .addEventListener("submit", function (event) {
          event.preventDefault();
          const formData = new FormData(this);
          for (const [key, value] of formData.entries()) {
            console.log(`${key}: ${value}`);
          }
        });
    </script>
  </body>
</html>

Cool Bits logo

Cool Bits

  1. To celebrate Vue’s 10th anniversary, Evan You spoke about the past and future of Vue at Vue.js Live Conf. I can’t wait to see what talk he’ll give about me when we’re celebrating our 10th anniversary of friendship in 2034.

  2. Deno 1.44 just came out with support for private npm registries and more Node compatibility improvements.

  3. Developer Nation’s brand new survey is a total win-win. Once you take it, they’ll donate to charity, give you a “virtual goodie bag” of helpful resources, and enter you for a chance to win a GoPro Hero12, Raspberry Pi 5, and lots more. Start now. [sponsored]

  4. Nadia Makarevich wrote an article called I tried React Compiler today, and guess what… I haven’t seen a cliffhanger that intense since the Season 1 finale of Severance.

  5. Fred K Schott wrote about Zero-JavaScript View Transitions, a new feature coming to Astro later this year.

  6. Expo just added experimental react-compiler support.

  7. Split created this case study on Moving Faster and Safer – which shows how they helped one team go from 2 deployments per day to 64 deployments per day by “learning to break things responsibly.” Sadly, they weren’t around back in 2011 to teach my college roommate how to “break things responsibly” when he was coming home drunk at 1:00 am 😭. [sponsored]

  8. James Sinclair wrote An epic guide on how to compose JavaScript functions that take multiple parameters. Good luck on your epic lawsuit from Kent Dodds, my man.

  9. TK Kinoshita wrote about Optimizing INP for a React app and the performance learnings they gained along the way.

  10. Maxi Ferreira wrote an article called How deep is your DOM? I was always taught that it’s not polite to ask a person that, but I guess I’m just old fashioned.


Spot the Bug logo

Spot the Bug: Solution

Sponsored by Snyk

The form is missing the name attribute on the input elements, which is required for the form to be submitted correctly.

<!DOCTYPE html>
<html lang="en">
  <body>
    <h1>Registration Form</h1>
    <form id="myForm">
      <input type="text" name="username" placeholder="Username" />
      <input type="password" name="password" placeholder="Password" />
      <input type="email" name="email" placeholder="Email" />
      <button type="submit" id="submitBtn">Submit</button>
    </form>

    <script>
      document
        .getElementById("myForm")
        .addEventListener("submit", function (event) {
          event.preventDefault();
          const formData = new FormData(this);
          for (const [key, value] of formData.entries()) {
            console.log(`${key}: ${value}`);
          }
        });
    </script>
  </body>
</html>