<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel><title>Node.js — Trust is earned, not given</title><link>https://www.bobhuang.com/series/node-js/</link><description>Server-side JavaScript across the years it became a platform: async/await and promisification, streams and backpressure, worker threads, ES modules, AsyncLocalStorage, npm workspaces, the built-in test runner, global fetch, the permission model, require(esm), and graceful shutdown.</description><language>en</language><lastBuildDate>20 Aug 2024 12:00:00 GMT</lastBuildDate><atom:link href="https://www.bobhuang.com/series/node-js/feed.xml" rel="self" type="application/rss+xml"/><item><title>Node.js, part 24: graceful shutdown, structured logs, and the end of console.log in production</title><link>https://www.bobhuang.com/blog/1029/node-shutdown-logging-observability/</link><guid>https://www.bobhuang.com/blog/1029/node-shutdown-logging-observability/</guid><pubDate>20 Aug 2024 12:00:00 GMT</pubDate><description>A service is judged on its worst ten minutes, and the bugs that produce those ten minutes are almost never in your business logic. They are in shutdown, in…</description></item><item><title>Node.js, part 23: Node 22 — WebSocket client, glob, and magic bytes</title><link>https://www.bobhuang.com/blog/1028/node-22-websocket-glob/</link><guid>https://www.bobhuang.com/blog/1028/node-22-websocket-glob/</guid><pubDate>23 Apr 2024 12:00:00 GMT</pubDate><description>Node 22 reads like a release that went through the dependency list of an ordinary service and moved half of it into core. A WebSocket client, a glob…</description></item><item><title>Node.js, part 22: require(esm) — the dual-package problem finally closes</title><link>https://www.bobhuang.com/blog/1027/node-require-esm-interop/</link><guid>https://www.bobhuang.com/blog/1027/node-require-esm-interop/</guid><pubDate>16 Jan 2024 12:00:00 GMT</pubDate><description>Part 5 left an asymmetry standing: a module could import CommonJS, but CommonJS could not require an ES module. Every library author paid for it, usually by…</description></item><item><title>Node.js, part 21: single executable applications — shipping a binary without Node</title><link>https://www.bobhuang.com/blog/1026/node-single-executable-applications/</link><guid>https://www.bobhuang.com/blog/1026/node-single-executable-applications/</guid><pubDate>26 Sep 2023 12:00:00 GMT</pubDate><description>"Install Node 20 first" is a fine prerequisite for a developer tool and an impossible one for a colleague in finance, a CI image you do not control, or an…</description></item><item><title>Node.js, part 20: a real CLI in one file — parseArgs, readline, and exit codes</title><link>https://www.bobhuang.com/blog/1025/node-cli-parseargs-readline/</link><guid>https://www.bobhuang.com/blog/1025/node-cli-parseargs-readline/</guid><pubDate>13 Jun 2023 12:00:00 GMT</pubDate><description>CLIs are where Node's standard library quietly became complete. Argument parsing, interactive prompts, coloured output, and process control are all core now…</description></item><item><title>Node.js, part 19: the permission model — capability-based security for a process</title><link>https://www.bobhuang.com/blog/1024/node-permission-model/</link><guid>https://www.bobhuang.com/blog/1024/node-permission-model/</guid><pubDate>21 Feb 2023 12:00:00 GMT</pubDate><description>Historically a Node process could do anything the user running it could: read any file, open any socket, spawn any binary. That is a lot of power for a build…</description></item><item><title>Node.js, part 18: Corepack — pinning the package manager instead of documenting it</title><link>https://www.bobhuang.com/blog/1023/node-corepack/</link><guid>https://www.bobhuang.com/blog/1023/node-corepack/</guid><pubDate>15 Nov 2022 12:00:00 GMT</pubDate><description>"We use pnpm 8" lives in a wiki, in CI config, in a README, and in someone's global install — four places that drift. Corepack, shipped with Node from 16.9 and…</description></item><item><title>Node.js, part 17: the built-in test runner and watch mode</title><link>https://www.bobhuang.com/blog/1022/node-test-runner-watch/</link><guid>https://www.bobhuang.com/blog/1022/node-test-runner-watch/</guid><pubDate>09 Aug 2022 12:00:00 GMT</pubDate><description>Jest, Mocha, Vitest, ts-node, nodemon, chokidar — an ordinary Node project used to begin with a page of devDependencies that existed to run and re-run its own…</description></item><item><title>Node.js, part 16: Node 18 — global fetch, Web Streams, and the shrinking dependency list</title><link>https://www.bobhuang.com/blog/1021/node-18-global-fetch-webstreams/</link><guid>https://www.bobhuang.com/blog/1021/node-18-global-fetch-webstreams/</guid><pubDate>19 Apr 2022 12:00:00 GMT</pubDate><description>Node 18 shipped in April 2022 with fetch as a global. Read casually that sounds like convenience; in practice it ended a decade of one of the ecosystem's…</description></item><item><title>Node.js, part 15: diagnostics_channel — publishing what happens inside your app, without an event emitter</title><link>https://www.bobhuang.com/blog/1020/node-diagnostics-channel/</link><guid>https://www.bobhuang.com/blog/1020/node-diagnostics-channel/</guid><pubDate>28 Sep 2021 12:00:00 GMT</pubDate><description>Instrumentation has an awkward requirement: the code that reports must not depend on the code that listens, and neither may depend on the other's absence. An…</description></item><item><title>Node.js, part 14: the profiler you already have — --cpu-prof, heap snapshots, and the flame graph</title><link>https://www.bobhuang.com/blog/1019/node-node-profiler-cpu-heap/</link><guid>https://www.bobhuang.com/blog/1019/node-node-profiler-cpu-heap/</guid><pubDate>15 Jun 2021 12:00:00 GMT</pubDate><description>"It's slow" is not a diagnosis, and adding console.time everywhere is not a measurement. Node ships a CPU profiler, a heap snapshot mechanism, and a diagnostic…</description></item><item><title>Node.js, part 13: npm workspaces — a monorepo without adding a tool</title><link>https://www.bobhuang.com/blog/1018/node-npm-workspaces-monorepo/</link><guid>https://www.bobhuang.com/blog/1018/node-npm-workspaces-monorepo/</guid><pubDate>02 Mar 2021 12:00:00 GMT</pubDate><description>Splitting a codebase into packages usually comes with a decision: adopt a monorepo tool (Lerna, Nx, Turborepo) or duplicate everything. npm 7 — bundled with…</description></item><item><title>Node.js, part 12: top-level await — when a module is its own init sequence</title><link>https://www.bobhuang.com/blog/1017/node-top-level-await/</link><guid>https://www.bobhuang.com/blog/1017/node-top-level-await/</guid><pubDate>10 Nov 2020 12:00:00 GMT</pubDate><description>Before top-level await (Node 14.8), a module that needed data before it could export anything had exactly one shape: export a promise, and make every importer…</description></item><item><title>Node.js, part 11: fs.promises and AbortController — doing two things at once, then stopping one</title><link>https://www.bobhuang.com/blog/1016/node-fspromises-abortcontroller/</link><guid>https://www.bobhuang.com/blog/1016/node-fspromises-abortcontroller/</guid><pubDate>18 Aug 2020 12:00:00 GMT</pubDate><description>Two changes made cancellation a first-class idea in Node. The file system got a real promise API (fs.promises, later node:fs/promises), and the AbortController…</description></item><item><title>Node.js, part 10: AsyncLocalStorage — request-scoped context without threading it through every call</title><link>https://www.bobhuang.com/blog/1015/node-asynclocalstorage-request-context/</link><guid>https://www.bobhuang.com/blog/1015/node-asynclocalstorage-request-context/</guid><pubDate>26 May 2020 12:00:00 GMT</pubDate><description>A request arrives, and forty frames deeper a function wants the request id so it can log it. The alternatives are all unpleasant: pass it as a parameter…</description></item><item><title>Node.js, part 9: optional chaining and nullish coalescing — the defensive code you can delete</title><link>https://www.bobhuang.com/blog/1014/node-optional-chaining-nullish/</link><guid>https://www.bobhuang.com/blog/1014/node-optional-chaining-nullish/</guid><pubDate>11 Feb 2020 12:00:00 GMT</pubDate><description>Node 14 landed V8 8.1 and with it two operators that had been stuck in proposal limbo for years: ?. and ??. They look like syntax sugar and they are — but they…</description></item><item><title>Node.js, part 8: getting dependencies under control — lockfiles, npm ci, and audit</title><link>https://www.bobhuang.com/blog/1013/node-dependency-hygiene/</link><guid>https://www.bobhuang.com/blog/1013/node-dependency-hygiene/</guid><pubDate>19 Nov 2019 12:00:00 GMT</pubDate><description>An application's dependency tree is code you did not write, did not review, and ship to production on every deploy. Node's ecosystem is also the largest one…</description></item><item><title>Node.js, part 7: HTTP/2 in core — multiplexing, headers, and the end of the connection pool hack</title><link>https://www.bobhuang.com/blog/1012/node-http2-in-core/</link><guid>https://www.bobhuang.com/blog/1012/node-http2-in-core/</guid><pubDate>13 Aug 2019 12:00:00 GMT</pubDate><description>HTTP/1.1's workaround for concurrency is to open several TCP connections and keep them alive, because one connection carries one request at a time. HTTP/2…</description></item><item><title>Node.js, part 6: the EventEmitter — and the 'error' event that crashes your process</title><link>https://www.bobhuang.com/blog/1011/node-eventemitter-error-handling/</link><guid>https://www.bobhuang.com/blog/1011/node-eventemitter-error-handling/</guid><pubDate>21 May 2019 12:00:00 GMT</pubDate><description>Almost every Node API is an EventEmitter underneath: servers, sockets, streams, child processes, the process itself. It looks like the simplest thing in the…</description></item><item><title>Node.js, part 5: ES modules arrive — import, export, and the interop rules</title><link>https://www.bobhuang.com/blog/1010/node-esm-vs-require/</link><guid>https://www.bobhuang.com/blog/1010/node-esm-vs-require/</guid><pubDate>05 Feb 2019 12:00:00 GMT</pubDate><description>For years require() was the only way to load code in Node, and it was genuinely different from the import the browser wanted. Node 12 made ES modules work…</description></item><item><title>Node.js, part 4: worker threads — real parallelism for CPU-bound work</title><link>https://www.bobhuang.com/blog/1009/node-workers-threads-parallelism/</link><guid>https://www.bobhuang.com/blog/1009/node-workers-threads-parallelism/</guid><pubDate>27 Nov 2018 12:00:00 GMT</pubDate><description>Node's single thread is a feature until someone hands it a CPU-bound job. A tight loop blocks the event loop, so every other request waits — and async/await…</description></item><item><title>Node.js, part 3: streams, backpressure, and why pipeline() replaced .pipe()</title><link>https://www.bobhuang.com/blog/1008/node-streams-pipeline/</link><guid>https://www.bobhuang.com/blog/1008/node-streams-pipeline/</guid><pubDate>11 Sep 2018 12:00:00 GMT</pubDate><description>Streams are Node's answer to data larger than memory, and the source of its most misdiagnosed bug: a process whose memory climbs while it copies a file. The…</description></item><item><title>Node.js, part 2: util.promisify and living with callbacks</title><link>https://www.bobhuang.com/blog/1007/node-util-promisify/</link><guid>https://www.bobhuang.com/blog/1007/node-util-promisify/</guid><pubDate>14 May 2018 12:00:00 GMT</pubDate><description>Everything in Node's standard library was a callback API first, and the ecosystem is full of third-party modules written the same way. You do not have to wrap…</description></item><item><title>Node.js, part 1: async/await without the callback pyramid</title><link>https://www.bobhuang.com/blog/1006/node-async-await-basics/</link><guid>https://www.bobhuang.com/blog/1006/node-async-await-basics/</guid><pubDate>19 Feb 2018 12:00:00 GMT</pubDate><description>For most of Node's first decade, "asynchronous" meant a callback and a growing pile of indentation. Node 8 shipped async/await on top of promises, and Node 10…</description></item></channel></rss>