[0] https://nodejs.org/api/cli.html#-require-module
[1] https://nodejs.org/api/module.html#moduleregisterhooksoption...
For reference, the main author of Nub is Colin McDonnell who created Zod and even worked at Bun at some point.
(When I was investigating this it was very early in Node’s `--import` story, but there were several edge cases with the more common ESM-to-CJS approaches that I wanted to address. Most were probably exceedingly niche concerns, but I’d expect top-level await to affect a meaningful subset of users.)
Relatedly Node.js recently (2025) introduced a synchronous version of its resolver hook registration API (`module.registerHooks()`) specifically to improve performance over the old async `module.register()` API. It was a big unblocker for Nub. For the interested, the async API added 19ms fixed registration overhead + about 130us additional overhead per import.
Which flag Nub uses here doesn't impact userland at all, TLA is supported wherever it's supported by Node.js itself.
0 issues, ridiculously fast.
This looks to support both the built-in stripping as well as actual TypeScript.
https://github.com/nodejs/typescript/issues/51#issuecomment-...
I've got a couple of decent-sized products running on Deno (and I've been a fan since it came out, not so much since 1.0 and 2.0, but still feel it's better than Node), but Node has been catching up and Deno has slowed down, so this might be the "compatibility middleware" that'll get me to move things back to Node.
Will keep a close eye on it.
A small scrappy team can prove out a good idea because failure is not a catastrophic risk to them. In short, forks are part of a healthy ecosystem.
Simple example: Node is the only serious OSS software I know of that has no way to document its config (in the config file itself). It's moronic! The Node people just adopted JSON without a thought, and then refused to consider any alternatives (even "JSON with comments").
When an organization digs into bad decisions, the only way to fix them is to start something new. The entire JS ecosystem will never have documentation on its config as long as everyone keeps building on top of Node.
(And there are many other issues like this in the Node ecosystem; the utter absurdity of not being able to document config is just my personal pet peeve.)
Tangential but this also drives me absolutely nuts. If I have to see `"//": "some comment"` one more time I'm gonna lose it.
Why can't you fix this while embracing existing tech? I can imagine monkeypatching Node & NPM to add support for JSONC or JSON5 or whatever in the same way that Nub adds various features via monkeypatching. Is there some architectural reason that can't work?
You'd need `npm publish` to compile it down to plain JSON when publishing, but that seems like an okay compromise.
Nub could absolutely support a config file and use it to set NODE_OPTIONS or flags in the node child process. There's no reason to throw out the baby with the bathwater due to DX concerns like this. That's a key part of the concept Nub is trying to prove. (To be clear I'm quite content to conform to Node's no-config-file policy at the moment.)
I'm imagining pnpm or others being able to adopt a package.json file that allows comments, then, when actually publishing, ensuring the published package.json is regular JSON.
It feels like this is missing something or using a nonnative library as a supplemental addition.
https://nodejs.org/learn/getting-started/websocket
It is under the site's learn tab, but never mentioned in the API/library documentation.
It's also weird because the only difference between a WebSocket client and server is that a server is a connection listener that responds to the handshake. The client is responsible for absolutely everything else: send messages, receive messages, initiate the connection, kill the connection, ping/pong. After the client accepts the server's handshake response the server becomes the other client performing exactly the same functionality. Node could have been doing that all along since adding client support.
P.S. The entire Bun’s anti-AI hysteria makes me very sad, sometimes it feels like a directed campaign
But also, I know “rewrite in Rust” is a meme but if you’re doing something new, why not? I can’t see a good argument that a pile of shell scripts would be a superior way to organise things.
I’m wondering how that works. Deno has very complicated import resolution, so building my own import resolver to be compatible with it is a bit of a pain. (This is for a custom lint-like tool.)
NODE_COMPAT=0 nub index.ts
nub --node index.ts
I'll investigate a `nub build` that would do the transpilation upfront and properly chunk/bundle a prod build. It's a good idea. But yes, Nub's overhead (both time and space) is generally negligible relative to Node itself.Re: added attack surface: the most obvious one is that Nub loads .env files (same as Bun/Next/Vite) so be aware of that. All of Node's permission flags are passed through as well. I won't claim there's no additional attack surface, but it doesn't have much surface area, just a Rust wrapper that spawns `node` ultimately.
HN itself renders * as emphasis, but not ` for "code"; this doesn't mean HN is a broken markdown machine or that i'm a bot. many hn comments use plain text conventions for links, see examples that use footnote style markdown-like links[0], I was [doing markdown links here back in 2017](https://news.ycombinator.com/item?id=14763397) even though they've never been parsed by HN.
This kind of semantic formalism in text goes way back, its not so different from something like Chicago style citations first published in 1906 [1].
[0]: https://news.ycombinator.com/item?id=47258996
[1]: https://www.chicagomanualofstyle.org/dam/jcr:bba47b07-61ba-4...
We've already pulled changes since that PR landed.
It would add an extra dependency though
The other pieces of the toolkit could absolutely be used: package manager, script runner, package runner. Works with anything that implements the Node module resolution algorithm (actually Yarn PnP also works out of the box...).
One suggestion, for package management you should just wrap pnpm, my desire to move to anything else is nil.
You can also move over to Nub from pnpm incrementally if you want the performance or security wins. It has complete pnpm compatibility: flag for flag identical CLI, reads and writes from your pnpm-lock.yaml, and respects your expecting configs completely. Nub and pnpm can be used simultaneously by different teammates without lockfile churn. This is a key design goal, and its what I mean by "incrementally adoptable". But yeah `nub install` will almost certainly work in your repo out of the box. (File an issue otherwise.)
https://nubjs.com/docs/install/pnpm
Same is true for npm, yarn, and bun as well. It detects your current package manager (based on package.json#packageManager or lockfile existence) and runs in "compatibility mode" for that specific package manager.
FROM node:26-slim
RUN npm i -g @nubjs/nub
Works with any Node version down to 18.19 but recommend 22.15+ for best performance (that's when synchronous registerHooks was introduced[0])[0] https://nodejs.org/api/module.html#moduleregisterhooksoption...