The reason is stability.
On server side, I can choose stable components. Usually this means I choose Java and a bunch of very carefully selected libraries such as FreeMarker. Needless to say, every library apart from Java's standard libraries is treated as disposable, so I access the external libraries through a self-made wrapper. This means I can change easily from one library to another if the requirement arises.
Whenever I update Java to a new version, it usually works well because Java is an extremely stable component even across major version updates. And also, every server I have is running the same Java version. Not every client is running the same JavaScript implementation.
On client side, I cannot choose stable components. The browser makers will force me to choose JavaScript, a language that I particularly don't like, but one that I am forced to use. (And don't tell me about languages that are compiled to JavaScript, they are horrible!) The JavaScript implementation of every browser is different. This means it is a total hell to test my product with every supported browser version.
My solution? I perform as much processing as I can on the server side, and the client side is only a lightweight wrapper that sends data to the server and receives data from the server in the form of JSON and HTML fragments. Avoid XML; use JSON instead.
I don't do client-side templating; I render the content on the server to a HTML fragment that I then assign using the .innerHTML
attribute to various placeholder elements on the client side. This keep the technology stack as simple as possible, because I don't need two template engines (a Java one and a JavaScript one).
The drawback is obviously speed-of-light latency; half a second of latency isn't uncommon between continents.
Do consider that your clients these days may be smartphones. Smartphones have a limited battery life, so if you're doing heavy computation, better to offload it to your servers. However, simple things can be more energy-efficient when done on the client side because then you can avoid radio access. But the main argument, stability, may mean it actually may make sense to offload even simple computation to the server.
As an addendum, as already observed in some answers, you gain security as well. If application logic is entirely on the client side, somebody can e.g. set a price to whatever thing they are going to purchase from your online web shop.
Obj.Obj.func
butObj.Func
. This is also better utilization of Namespace as only the Object is global client side. Moving forward all my code/functions will be/try to be usable client or server side as I write and I can decide later when to offload processing.