I've been saying it for years - the hard part is not "server side" vs "client side", it's making sure the state stays consistent between those 2 buckets.
If you want to remove the hell from your life, you need to be all in on one or the other.
For us, we've been keeping all state server-side using things like Blazor and hand-rolled js-over-websocket UI frameworks. We never have to worry about more than ~10k users, so this works out great for us.
If we were webscale, we'd have to consider client side options.
Even in smaller applications this is incredibly relevant.
I've recently written something that's meant to interface on a local area network, just controlling something on another computer, literally just one or two users at a time -- thing is the precision of floating points are a big thing here, and we have to consider that. So all of the bignum stuff had to stay server-side in C++ after much messing around doing math client side in javascript only to learn the hard way how completely broken that is. Fun fact - You can't maintain state when floats start to drift off of values they were supposed to land on due to javascript's crappy math libs
Javascript can get messy even if you just need integers, since even naively used integers are stored as doubles. This means that sending a random 64-bit identifier from a server to a client and just trying to read it as an int can give the wrong value if you aren't careful.
Recently I've been dabbling in developing online multiplayer games.
After some agony trying to make the chaos go away (rewinding time, merging conflicting physics states...), I realized I could actually harness it by re-framing the product from something serious into something lighthearted (eg. making goofy physics the whole point of the game).
At worst, it lowers the expectations (eg. relative to something serious/competitive where jankiness is unacceptable), and at best may actually produce laughter. I hope.
I'm curious, what problems did you have with JavaScript math? I had the impression it was bog standard IEEE 754 same as every other language nowadays, but I have never tried doing any serious calculation in that language.
I clearly stated we were working on floating points here, ones originally provided by the c++ application.
There was a thought to just make everything into big integers here but for this particular application it really just was the realization that all of this stuff was better off server side anyways for state maintenance reasons
I've never worked on a project that could be "all in" on client side state. To be all in there means your application doesn't need the network at all except as a method to distribute your application. One step away from that would be something that is completely client authoritative - I've also never worked on a project like that.
Note that even if your code has zero Javascript, you can still have state mixed between client and server: instead of living in Javascript, it lives in the html, oftentimes as values in form elements. Even though the html is generated on the server, it still lives in the client, ready for the client to do things with it - such as submit a form with information that is 8 hours out of date.
There are obviously ways around this, but it's still something one should keep in mind.
Live update via websockets can kinda get around this. As long as there are no bugs and all state is properly transmitted and processed in a deterministic order. But it's still effectively a synchronization process and stuff can go wrong.
You're technically correct (the best kind!) but in practice one can largely ignore server state in some applications.
I've got a side project where the data is stored server side. In practice, that server side data might as well be a saved file on the clients hard drive.
Is it "all in" on client state? Not really. Do I ever need to worry much about synchronization? Also no. The synchronization is just "send it to the server when it changes, put an error bar up if that fails". Pretty simple.
It's a bit network heavy, but in this case there are other, heavier parts of the app. There are options if data size ever does become an issue - for now it's not.
Incidentally, I feel like this is where something like MongoDB really is a decent choice. The client would probably just preload the data anyway if it were normalized and in Postgres somewhere. API serves out JSON. Why not just... load the JSON out of the DB?
that's pretty much how i build all my websites. not with mongodb but another reusable generic CRUD backend. it's not much more network heavy than a static or serverside rendered site and the server doesn't need to keep any state other than the data itself. any custom state that the client wants to store on the server is just saved as additional server data.
The correct answer to this is that state lives in the url, which is shared between client/server. This is a simplistic solution for many applications, but still achievable on some level.
The right model for attacking this problem is multiplayer video games. That is the technical space where the questions of synchronizing a shared concept of what the universe should look like among multiple distinct nodes separated in space and time with real-time latencies has been thoroughly investigated.
It is also some of the more complicated and intricate code that you will find in the wild, so best of luck.
Blazor Server and other HTML over the wire frameworks (Livewire, Hotwire, HTMX, etc.) are the new sweet spot for a lot of LoB web applications I think.
The amount of leverage you can get out of these paths is pretty incredible. The fundamental idea is really simple too if you boil it down to the absolute minimum essence...
The following 6 lines of javascript is all it takes to connect a hot pipe from server to client and dynamically invoke whatever is required.
function StartApplication() {
document.ApplicationSocket = new WebSocket(...);
document.ApplicationSocket.onmessage = function (e) {
return new Function('use strict";\n'+e.data)();
}
}
Anything that needs to talk back to the server would just send a message on the same socket.
This is pretty similar to how Blazor Server works, except we are able to bootstrap our client off <1kb of javascript+html source.
We were already doing this kind of workflows with WebForms and Java Server Faces alongside DHTML, but naturally we weren't cool, so the kiddies took 12 years to re-discover the wheel.
> I've been saying it for years - the hard part is not "server side" vs "client side", it's making sure the state stays consistent between those 2 buckets.
If you want to remove the hell from your life, you need to be all in on one or the other.
A full rendered web page is the server state displayed on the client. Except of removing all dynamic in page interaction, you are ALWAYS in risk for de-synched state between client and server. There is no single side state, as long as someone sees your server sate.
Recently I started to toy with a PHP framework that works like Blazor and has all the state on the server. It also has the virtual DOM on the server. This works great even without sockets or polling. All requests from the client to the server will have a virtual DOM diff as result.
If you want to remove the hell from your life, you need to be all in on one or the other.
For us, we've been keeping all state server-side using things like Blazor and hand-rolled js-over-websocket UI frameworks. We never have to worry about more than ~10k users, so this works out great for us.
If we were webscale, we'd have to consider client side options.