Skip to main content

3 posts tagged with "Browser platform"

Web platform primitives the runtime is built on.

View All Tags

A Nuxt dev server in a tab cost 3.46 GB, and the biggest thing we could actually shrink was the filesystem

· 10 min read

A tab running nuxt dev was using 3.46 GB. That is not a number you optimise your way out of with a hunch, and the hunch everybody has is the same one: bundlers are memory hogs, so it must be the bundler.

It was not the bundler, whose entire contribution was 22.5 MB. It was three other things, and they are not even measured in the same units: a filesystem holding 929 MB of node_modules as bytes, a persistence layer writing 4.7 GB to store 53 MB, and an editor spending 621 MB parsing one set of type definitions twice.

This post is the autopsy rather than a list of tips, because the useful part is which assumptions turned out to be wrong.

Three ways to isolate a preview, and the Cloudflare wildcard trick

· 8 min read

When an in-browser IDE runs your dev server and shows you the result, the result has to be served from somewhere. The easy answer is the origin you already have: put the preview at /preview/5173/ on the IDE's own domain, let the Service Worker route by path, ship it.

That is what we did, and it is a security problem.

Same origin means the same cookie jar, the same localStorage, the same IndexedDB, the same OPFS, the same Cache Storage, the same Service Worker scope. Preview code, which includes every npm package the project installed and anything an AI assistant just generated, sits inside the IDE's origin. It can read the editor's session state, corrupt its persistence, and call its same-origin APIs. Previews are not isolated from the IDE, and they are not isolated from each other.

Fixing this properly took three attempts, and each one ran into a different piece of web platform trivia.

The one browser API that makes a Node runtime possible

· 8 min read

Every browser-based Node runtime runs into the same wall on day one, and it is not the filesystem, the module resolver, or the process model. It is one line of code:

const config = fs.readFileSync("/app/package.json", "utf8");

That call has to return bytes. Not a promise, not a callback: bytes, on the next line. And reading those bytes means asking something else for them, which in a browser means waiting. Browsers are built on exactly one promise to the user: nothing blocks. So the very first thing Node requires is the one thing the platform refuses to do.

There is precisely one exception, and this post is about building on top of it.