Putting the "p" in npm

Issue #174.March 31, 2023.2 Minute read.
Bytes

Welcome, friends!

Big thanks to those of you who shared 🕹️ react.gg! Someone posted it to Hacker News and we hit the front page (!!) for a few minutes (!!) until it got flagged, lol. The orange site giveth, and the orange site taketh away.

Today’s issue: Weird spammers take over npm, the first web designer to win an EGOT, and the best way to practice a knuckle puck.

Welcome to #174


Eyeballs logo

The Main Thing

Mighty ducks screenshot with pnpm and npm logos

Our most esoteric 90s pop culture meme yet

Putting the “p” in npm

Pnpm just released v8.0 on Monday. And while there aren’t a bunch of big new features, pnpm itself has been getting a lot of hype lately. They even 5x’d their number of total downloads last year and continue to grow 📈.

So what makes this package manager unique, and why are its usage graphs shaped like my D2: The Mighty Ducks commemorative hockey stick from 4th grade? Let’s dive in.

Quick background: Back in 2017, Zoltan Kochan released v1 of pnpm, which TIL stands for “performant npm.” I always assumed it stood for “pneumonia npm”, because my lungs would fill up with fluid whenever I used it — but it turns out that was just because my old office had a bunch of asbestos 🤷‍♂️.

But “performant npm” is actually a great name, because that’s exactly what it is — a faster, more efficient replacement for npm (and Yarn) that comes with solid monorepo support and mostly feels like you’re just using npm. Here’s how it works:

  • With Yarn and npm, if you have 100 projects using a dependency on your machine, you’ll have 100 copies of that dependency saved on your disk. They resolve those dependencies by using hoisting to flatten their node_modules. This eats up a lot of disk space and can cause slow installs (as you’ve probably experienced).

  • Pnpm’s key insight was to use a content-addressable store instead, which stores each of your dependencies only once in a global store on your home folder. If you need different versions of the package, only the files that differ get added to the store (instead of the entire package).

  • They do this via a non-flat node_modules directory, which creates a nested structure of dependencies, where every package and file inside the folder is hard linked to the store — saving you time and disk space 🤝.

Bottom Line: Yarn and npm have started adopting some of these ideas, and Bun is coming in hot with its own package manager that claims to be fast af too. But for now, the pnpm hockey stick growth chart shows no signs of slowing down. Now excuse me while I go outside to practice my knuckle puck.

        

Retool logo

Our Friends
(With Benefits)

Man typing while looking at the back of two monitors

We're all backend devs now 😈

Retool Database just launched 👀

I’m pretty sure Retool’s mission statement is, “Be a developer genie that grants unlimited wishes.”

The latest magic is Retool Database. It lets you build apps with a fully managed PostgreSQL database with no setup required. That means you can ditch your janky spreadsheets forever — and convert your Google Sheets and Airtable Bases into Postgres tables in a few clicks.

The goal here is to give you the power of a scalable Postgres DB, with the speed and convenience of a spreadsheet. Here’s how it works:

  • When you sign up for Retool, they spin up a real, Postgres DB for you that’s ready to scale.

  • You can use their database UI to build your schema — add tables, configure fields, and upload CSVs like you’re working in a spreadsheet.

  • Then you can write real SQL queries for all of your Retool apps (and use it with non-Retool apps too).

Check it out.


Tip logo

The Tip

Sponsored by Unlayer

They created this drag-and-drop editor and page builder for your SaaS application that’s embeddable and guaranteed to save you weeks of dev time.

Chances are if you wrote a form in the last 5 years, it looked like this:

import * as React from 'react';

function Form() {
  const [name, setName] = React.useState('')
  const [email, setEmail] = React.useState('')

  function handleSubmit(e) {
    e.preventDefault()
    // Do something with the data
  }

  return (
    <form onSubmit={handleSubmit}>
      <input type="text" name="name" value={name} 
        onChange={(e) => setName(e.target.value)} />
      <input type="text" name="email" value={email} 
       onChange={(e) => setEmail(e.target.value)} />
      <button type="submit">Submit</button>
    </form>
  )
}

But how would you do this in pure HTML? Answer below.


Cool Bits logo

Cool Bits

  1. Speaking of npm, Gabi Dobocan wrote on the Sandworm blog about how 50% of new npm packages are SEO spam right now — promoting things like fake Fortnite V-bucks (ew) and free ebooks (double ew). I emailed Nat Friedman to ask him why npm install hot-singles-near-me isn’t working, but I haven’t heard back.

  2. Looking for a good way to monitor your React Native app? The New Relic team wrote some helpful documentation around monitoring React Native applications with New Relic. [sponsored]

  3. Jim Nielsen wrote about Types in JavaScript With Zod and JSDoc for those of us who might like types, but don’t like like types.

  4. Update: over 5,600 packages about John Wick have now been uploaded to npm, which means that .02% of npm is currently dedicated to Hollywood’s most beloved assassin. I know this probably seems like something we would do, but I swear it wasn’t us.

  5. JP Camara wrote about how he made Tanstack Table 1000x faster with a one-line change

  6. Tailwind CSS v3.3 just came out with an ESM and TS support, logical properties, and an extended color palette for darker darks. I just hope they have the full Tom Haverford collection of “obsidian, onyx, midnight, lost soul, rolling blackout, sleeping panther, and Void by Armani.”

  7. Lots of you have asked, so we wanted to share that the react.gg domain cost us $7k (😮‍💨) and we built the site using Astro and React (🚀 + ⚛️). Also, it was designed and built by our very own Lynn Fisher (🐐) — whose past web projects have received multiple design awards (nbd). This year, we’re hoping she becomes the first web designer to win an EGOT 💚.


The browser has a built in API called FormData that allows you to easily get the data from a form.

<form>
  <input type="text" name="name" />
  <input type="text" name="email" />
  <button type="submit">Submit</button>
</form>

<script>
  const form = document.querySelector('form')
  form.addEventListener('submit', (e) => {
    e.preventDefault()
    const formData = new FormData(form)
    const email = formData.get('email')
    const name = formData.get('name')
    // Do something with the data
  })
</script>

Even if you’re using React, FormData makes it easy to get the data without having to manage state for each input.

import * as React from 'react';

function Form() {
  function handleSubmit(e) {
    e.preventDefault()
    const formData = new FormData(e.target)
    const email = formData.get('email')
    const name = formData.get('name')
    // Do something with the data
  }

  return (
    <form onSubmit={handleSubmit}>
      <input type="text" name="name" />
      <input type="text" name="email" />
      <button type="submit">Submit</button>
    </form>
  )
}

Bonus:

FormData is also one of the Request body types for the Fetch API, so if you are using an edge function to handle your form submissions you can use FormData to easily get the data from the request.

function handleRequest(request) {
  const formData = await request.formData()
  const email = formData.get('email')
  const name = formData.get('name')
  // Do something with the data
}