Today’s issue: The unknowable mystery of Remix & React Router, a sure-fire way to rebuild my self esteem, and celebrating the birthday of a programming language you don’t even like.
Welcome to #341.
Node "borrowing" features from Deno and Bun
Back in May, we wrote about how Bun and Deno helped wake up a sleeping giant in the form of Node.js 22.
That release was packed with impactful features for the OG runtime, after what felt like years of merely incremental improvements. Yes, many of those features were already present in the next-gen runtimes, but Node users definitely weren’t complaining.
Fast forward to last month, and we saw Node 23 pick up right where v22 left off, giving us some experimental new features and adding stable support for others.
The biggest improvement in this release is the now-stable require()
support for ESM graphs, which lets you import an ES Module in CommonJS and have it just work.
Why this is a big deal: For years, developers have struggled with the transition from CommonJS to ES Modules, largely because you couldn’t require
an ESM in Node.js. This issue delayed the full adoption of ESM and led to debates about whether or not you should transpile your code to CJS before publishing to npm. But now, we can finally put all of that behind us 🙏.
Other highlights in Node 23:
The --experimental-strip-types
flag provides “initial TypeScript support” by stripping type annotations from .ts files, allowing them to run without transforming TypeScript-specific syntax.
Stabilized task runner lets you execute package.json
scripts by using node --run
, instead of needing to use npm, Yarn, or Bun.
The built-in test runner now comes with glob pattern support for coverage files, which simplifies running tests across multiple files.
Bottom Line: Between AI, politics, and JoJo Siwa speaking at Brown University, it’s clear that we’re living through uncertain times. But at least you’ll be able to tell your grandchildren that you also got to live through the golden age of JavaScript runtimes.
Me getting ready to mansplain sync engines to you
Wtf does that mean? First off, watch your language.
An object sync engine allows you to keep data in sync across users and devices for local-first apps by syncing an object graph between clients and a centralized server.
The Convex team has spent the last few months extending their own sync engine, so that the platform can provide a great batteries-included option for local-first apps.
And because they like to show off go the extra mile, Sujay Jayakar wrote this technical deep dive that breaks down the sync engine’s 3 main pieces:
The article compares Convex’s approach to other real-time frameworks like Replicache, and it shares how experienced teams evaluate tradeoffs when making complex technical choices.
Check out the blog post – Sujay previously worked on sync at Dropbox for a decade, and you can tell.
We’re expert, US-based consultants who have specialized in high-quality React Native development since 2015! Hire us to build, optimize, deploy, and support your React Native app.
What does this function do?
const surprise = (...fns) => input => fns.reduce(
(acc, fn) => fn(acc), input
)
I cordially invite you to take the State of React survey and vote for Bytes, react.gg, and other ui.dev things things you like about the React ecosystem. Will that finally fix my crippling self-esteem issues? There’s only one way to find out.
Ahmad Shadeed wrote the best article on the internet about how overflow: clip
works in CSS.
PropelAuth provides end-to-end managed user authentication for B2B use cases – and developers are weirdly obsessed very passionate about it. One founder said, “I’ve never come across a tool that works this well for authentication needs. Hands down, one of the best products I have ever used. 11/10 would recommend.” Their free tier is also very good. [sponsored]
Go just turned 15 years old, and I still have no idea what to wear to its quinceañera.
Elan Medoff wrote about conditional props in React using type discrimination. And if you were just like “oh, that’s exactly what I need” then I’m sending well wishes your way today.
Two Sentry engineers, Jenn Mueng and Ram Senthamarai are hosting this live demo of the new AI tools they built for Sentry. They promise to keep the AI hype to a minimum and just show you how they built smarter alerts and other cool features. [sponsored]
Jonathan Creamer got the memo for today and wrote this article about using TypeScript in Node.js scripts without actually writing TypeScript.
Remix 2.14 and React Router 6.28 were just released at the same time because they are both the same project, but also completely distinct projects with different priorities, but also one in spirit. And if that confuses you, it’s probably because you’re a hater.
Amelia Wattenberger wrote a visually beautiful article called LLMs as a tool for thought.
Daniel Schwarz wrote an in-depth article on the different (and modern) ways to toggle content, which everyone seems to really like. Kind of like this “different and modern” version of Get Low that Mark Zuckerberg made with T-Pain to give his wife as an anniversary gift.
What does this function do?
const surprise = (...fns) => input => fns.reduce(
(acc, fn) => fn(acc), input
)
It’s a pipe
function that allows you to chain multiple operations together by taking a series of functions as arguments and applying them in a specific order to the input.
Wow, words.
Instead of doing something like this.
const toUpperCase = str => str.toUpperCase()
const removeSpaces = str => str.replace(/\s/g, "")
const addExclamation = str => str + "!"
toUpperCase(removeSpaces(addExclamation("Subscribe to Bytes")))
You can do something like this.
const pipe = (...fns) => input => fns.reduce(
(acc, fn) => fn(acc), input
)
const formatString = pipe(toUpperCase, removeSpaces, addExclamation)
formatString("Subscribe to Bytes") // SUBSCRIBETOBYTES!
There’s currently a perpetual TC39 proposal for adding a true Pipe operator (|>) to JavaScript.