93 comments

[ 3.3 ms ] story [ 71.9 ms ] thread
About time! The whole dragging the feet on ESM adoption is insane. The npm are still stuck on commonjs is quite a lot. In some way glad jsr came along.
I blame tooling folks doing too good of a job abstracting the problem away, and no this of course isn't a jab at them.

probably 70 to 80% of JS users have barely any idea of the difference because their tooling just makes it work.

Yet more architecture astronaut behavior by people who really should just be focusing on ifs, fors, arrays, and functions.
Thank you for this. Very helpful as I was just starting to dig into node for first time in a few years.
This is great. I learned several things reading this that I can immediately apply to my small personal projects.

1. Node has built in test support now: looks like I can drop jest!

2. Node has built in watch support now: looks like I can drop nodemon!

I tried node:test and I feel this is very useful for tiny projects and library authors who need to cut down on 3rd party dependencies, but it's just too barebones for larger apps and node:assert is a bit of a toy, so at a minimum you want to pull in a more full-fledged assertion library. vitest "just works", however, and paves over a lot of TypeScript config malarkey. Jest collapsed under its own weight.
(comment deleted)
Don’t forget the native typescript transpiler which reduces the complexity a lot for those using TS
The killer upgrade here isn’t ESM. It’s Node baking fetch + AbortController into core. Dropping axios/node-fetch trimmed my Lambda bundle and shaved about 100 ms off cold-start latency. If you’re still npm i axios out of habit, 2025 Node is your cue to drop the training wheels.
Those... are not mutually exclusive as killer upgrade. No longer having to use a nonsense CJS syntax is absolutely also a huge deal.

Web parity was "always" going to happen, but the refusal to add ESM support, and then when they finally did, the refusal to have a transition plan for making ESM the default, and CJS the fallback, has been absolutely grating for the last many years.

16 years after launch, the JS runtime centered around network requests now supports network requests out of the box.
There has to be something wrong with a tech stack (Node + Lambda) that adds 100ms latency for some requests, just to gain the capability [1] to send out HTTP requests within an environment that almost entirely communicates via HTTP requests.

[1] convenient capability - otherwise you'd use XMLHttpRequest

This has been the case for quite awhile, most of the things in this article aren’t brand new
It kills me that I keep seeing axios being used instead of fetch, it is like people don't care, copy-paste existing projects as starting point and that is it.
With node:fetch you're going to have to write a wrapper for error handling/logging/retries etc. in any app/service of size. After a while, we ended up with something axios/got-like anyway that we had to fix a bunch of bugs in.
Node now has limited supports for Typescript and has SQLite built in, so it becomes really good for small/personal web oriented projects.
I feel like node and deno conventions are somehow merging (which is a good thing)
I've been away from the node ecosystem for quite some time. A lot of really neat stuff in here.

Hard to imagine that this wasn't due to competition in the space. With Deno and Bun trying to eat up some of the Node market in the past several years, seems like the Node dev got kicked into high gear.

Some good stuff in here. I had no idea about AsyncIterators before this article, but I've done similar things with generators in the past.

A couple of things seem borrowed from Bun (unless I didn't know about them before?). This seems to be the silver lining from the constant churn in the Javascript ecosystem

I think slowly Node is shaping up to offer strong competition to Bun.js, Deno, etc. such that there is little reason to switch. The mutual competition is good for the continued development of JS runtimes
(comment deleted)
Starting a new project, I went with Deno after some research. The NPM ecosystem looked like a mess; and if Node's creator considers Deno the future and says it addresses design mistakes in Node, I saw no reason to doubt him.
One thing you should add to section 10 is encouraging people to pass `cause` option while throwing new Error instances. For example

new Error("something bad happened", {cause:innerException})

It's wild that that's not what the section is about. Extending error is not new at-all.
Nice post! There's a lot of stuff here that I had no idea was in built-in already.

I tried making a standalone executable with the command provided, but it produced a .blob which I believe still requires the Node runtime to run. I was able to make a true executable with postject per the Node docs[1], but a simple Hello World resulted in a 110 MB binary. This is probably a drawback worth mentioning.

Also, seeing those arbitrary timeout limits I can't help but think of the guy in Antarctica who had major headaches about hardcoded timeouts.[2]

[1]: https://nodejs.org/api/single-executable-applications.html

[2]: https://brr.fyi/posts/engineering-for-slow-internet

Yeah, many people here are saying this is AI written. Possibly entirely.

It says: "You can now bundle your Node.js application into a single executable file", but doesn't actually provide the command to create the binary. Something like:

    npx postject hello NODE_SEA_BLOB sea-prep.blob \
        --sentinel-fuse NODE_SEA_FUSE_fce680ab2cc467b6e072b8b5df1996b2
Yeah, this one line gave it away for me: "you’re not just writing contemporary code—you’re building applications that are more maintainable..."

Look up dialectical hedging. Dead AI giveaway.

The LLM made this sound so epic: "The node: prefix is more than just a convention—it’s a clear signal to both developers and tools that you’re importing Node.js built-ins rather than npm packages. This prevents potential conflicts and makes your code more explicit about its dependencies."
I love Node's built-in testing and how it integrates with VSCode's test runner. But I still miss Jest matchers. The Vitest team ported Jest matchers for their own use. I wish there were a similar compatibility between Jest matchers and Node testing as well.
(comment deleted)
I see two classes of emerging features, just like in the browser:

1. new technologies

2. vanity layers for capabilities already present

It’s interesting to watch where people place their priorities given those two segments

> vanity layers for capabilities already present

Such as?

(comment deleted)
"SlopDetector has detected 2 x seamlessly and 7 x em-dash, would you like to continue?"
I use em-dash these days just to trigger tinfoil hats like you.
(comment deleted)