A Whole Website in a Single JavaScript

Issue #120.September 19, 2022.2 Minute read.
Bytes

Welcome to #120.

Today we’re giving away a wall-mounted T-Rex sculpture. The first one to solve the puzzle and respond to this email with the secret code wins.

The clue? A place that you go, with thoughts you can’t discard. Against your will, you’ll see shirts that go hard.

This week we’ve got acquisition rumors, a developer productivity report by My Chemical Romance, and literally nothing about the Ethereum Merge. Buckle up.


Eyeballs logo

The Main Thing

Npm trends graph of React Router with Remix pasted in front of React Router

When you're pre-revenue and the VC's need to see growth

ReRouterActMix 6.4

Back in March, The Remix team (who is also the React Router team) announced that they were ripping out “everything great about Remix’s data and async UI management” and putting it inside of React Router.

This would give React Router users (aka 50% of React developers) some cool new features without having to fully commit to Remix. And it would also give Remix a nice top of funnel growth strategy for acquiring new users. Win win.

Fast forward to last week, and The Merge™️ officially kicked off with the release of React Router v6.4. Here’s what the new ReRouterActMix looks like under the hood:

  • Loading Data — React Router now has the concept of “loaders”, which can pre-load and parallelize requests for each route.

  • Updating Data — The ’90s are cool again, so RR is bringing back forms. Routes can now handle submission navigation, cancellations, and race conditions for all of your “actions.”

  • Error Handling — “The vast majority of your application errors are handled automatically by React Router.” That’s a pretty bold claim, Cotton, because they’ve never seen my code.

  • UX Goodies — RR is giving away goodie bags for your users. We’re talking busy indicators, optimistic UI, scroll restoration, Skeleton UI and more — just in time for Halloween.

Bottom Line: It’s a smart business move for Remix to hitch its wagon to React Router (and its ~8 million weekly npm downloads). But it’s not November 2021 anymore, and VC’s have realized that companies need to “sell” a product for “real money” in order to produce “returns.”

Remix will eventually have to figure out how to do that if they want to be viable as a business, or maybe they’ll just join $BIGCO and keep living the dream.


FusionAuth Logo

Our Friends
(With Benefits)

A skeleton admiring the clothes of medieval person

"You built all of this in an hour? Incredible."

FusionAuth is the holy grail

Trying to build authentication from scratch is like trying to hold in diarrhea while meeting your future in-laws — it’s painful, complicated, and you’re one wrong step away from a complete disaster.

That’s why we’re huge fans of FusionAuth.

They’re a complete auth solution that takes care of all the gross stuff like SSO, MFA, user management, and security — and if you don’t know what one or more of these things are… you probably need it.

Their Free Community version is surprisingly robust (no credit card, no limits, and it’s free forever if you self host 🙏). That makes it great to learn with or use for side projects, but it also has a pretty seamless integration process for existing apps.

And if you ever get stuck, you can call their support line and talk to an actual engineer who really knows auth — instead of just typing your questions into a support chat box that no one will read (like some other auth companies I know).

Check it out and never worry about auth again.


Spot the Bug logo

Spot the Bug

Sponsored by talent.io

Curious about the current state of tech salaries? Here’s a great report by talent.io, the simplest way to find your next job.

const getCapitalizedInitials = (name) =>
  name
    .trim()
    .split(" ")
    .forEach((name) => name.charAt(0))
    .join("")
    .toUpperCase()

Cool Bits logo

Cool Bits

  1. Brian Clark wrote a deep dive on Best practices for creating a modern npm package. Surprisingly, he doesn’t seem to recommend the old “Russian Nesting Doll Technique” of IIFEs inside of IIFEs inside of more IIFEs. The web has become so complex lately.

  2. This Retool page gives a lot of cool examples of how you can build all types of dashboards, database GUI’s, and admin panels. I honestly have no idea how anyone built internal apps like this back in the PRD (Pre-Retool Days). [sponsored]

  3. Zach Leatherman (the maintainer of Eleventy) built a compiler for “single file components” that transforms into HTML, CSS, vanilla JS, and WebComponents. No word yet on how much Adobe is planning to acquire this for.

  4. DFlex is a drag-and-drop Javascript library that actually manipulates the DOM, instead of reconstructing it. I miss the days when “reconstructing the DOM, instead of manipulating it” was the selling point.

  5. Sarah Drasner, Minko Gechev, and Madleina Scheidegger spoke about the future of Angular during their keynote at ng-conf.

  6. James Williams wrote about The Shortest URLs on the Internet. Somehow, ui.dev didn’t make the cut?? I demand a recount.

  7. GitHub wrote about its research efforts to quantify Copilot’s impact on developer productivity and happiness. Now I just need Taking Back Sunday and My Chemical Romance to create a research report on how listening to mid 2000s pop-punk also improves developer productivity and happiness. Then all of my confirmation biases will be nice and… confirmed.

  8. Leo Kettmeir wrote a post on the Deno blog about creating A Whole Website in a Single JavaScript File. If he had chosen to clone a popular religious dating website for the demo, he would’ve had the best article title ever: “Christian Mingle in a JS Single.”


Spot the Bug logo

Spot the Bug: Solution

Sponsored by talent.io

We’re treating forEach as if it returned an array, when it actually returns undefined. Instead, we want to use map, which works similar to forEach, but also creates and returns a new array.

const getCapitalizedInitials = (name) =>
  name
    .trim()
    .split(" ")
    .map((name) => name.charAt(0))
    .join("")
    .toUpperCase()