← Back to context

Comment by fellowniusmonk

2 years ago

It's a realtime project, it organizes my whole life.

html, js, indexeddb, uwebsocket, redis, byob for private backup (uses s3 by default, I use r2 personally, also support google drive)

js dependencies are dexie, uwebsocket.js, luxon, morphdom.

Using indexeddb means all updates are persisted before rendering and transmission. Rendering is deterministic based on local db values, there is effectively no indeterminate state. Dropped socket connections are nbd as all updates are either timestamped or timestamped & crdt so data is always in sync and can be upserted with dexie. Delivering messages multiple times is rare but inconsequential.

Morphdom keeps ui updates fast and lets me use escaped template literals and a more laissez faire approach to query & rendering for ui components.

DOM node names/ids are distinct & semantic. They aren't obfuscated by a rendering pipeline so it's very easy to trace ui to db and code without relying on an IDE.

Components and dom node names are namespaced using js Sets and Proxies so that the apps namespaces are kept conflict free and it alerts you in console if you create a name conflict.

Only data the user hasn't synced is kept in memory on server, load is distributed by all servers having a persistent socket connection with each other and I use N character subdomain dns resolution to match first two characters+ of users uuids (aa.site.com, ab.site.com) to handle message passing against a redis pool.

This effectively means I have presharded the socket load by user but means I don't have to spin up new servers until the load warrants it for each subdomain. It runs on 1 server as simply as 20 and everything is fully evented.

This all means that the server is a single js file I can overwrite to hot reload.

Same with the client file except it's an html and js file.

The longer I've been doing this the more I believe that everything comes down to a proper data/database implementation. If you are disciplined with your schema, always use ids, and ensure data comes first... everything else becomes disposable and easily refactored.

Also, DOM ID obfuscation is insane for front end rendering engines, keep it semantic and matching your names/ids in code/db.