What breaks when you ship Next.js on Cloudflare Workers
A log of which npm packages don't survive the Workers runtime, what to swap them with, and the patterns that ended up mattering.
I've been building Finterm, a financial terminal that runs entirely in a browser tab, on Cloudflare Workers via @opennextjs/cloudflare. The promise is the obvious one — global edge runtime, near-zero cold starts, pay-per-request pricing. The catch is that Workers don't run Node.js. Every package in your dependency tree has to work in the Workers runtime, and a surprising number of common ones don't.
This is a rough log of what I had to rip out and what I replaced it with, plus a couple of patterns that turned out to be necessary on Workers but irrelevant on Node.
bcryptjs reaches for crypto.randomBytes and a few other Node primitives that aren't polyfilled in Workers. Argon2id is the modern alternative anyway, and @noble/hashes exposes a pure-JS implementation that runs anywhere and lines up with current OWASP guidance. The migration was a one-line change in the password hasher plus a re-hash on next login.
For the news reader I needed to extract article bodies from arbitrary HTML. cheerio pulls in parse5, which doesn't run on Workers, and jsdom is even further away from compatibility. htmlparser2 is SAX-style streaming and pure JS, so it runs anywhere — but you have to walk the events yourself rather than querying a tree. Worth it for the runtime portability.
Not a Workers issue specifically, but I hit it harder because of Workers. Yahoo's quoteSummary, options, and profile endpoints require a session cookie and a crumb token bound to that session. The dance: first you GET https://fc.yahoo.com/, which returns 404 with Set-Cookie for A1 and A3; then you GET /v1/test/getcrumb with those cookies, which returns the crumb as plain text; then every gated request needs that cookie plus &crumb=... appended to the URL.