From a developer's perspective, a web application (called a website back in the days) is made of two parts: The server side code and the client side code.
Writing a program for a web browser is something different than writing for a server. Most of the time, web developers do both as client-side programming is seldom enough to build a UI. Both programming are similar in many ways: You write loops, classes, functions, tests, etc. but they are also very different. This article tries to explain the fundamental differences and what it means for the developer.
Control over the runtime environment
When you program server side code, you know exactly where and how it's going to run, because you have the control of your server. You know which version of Java or php, which CPU, what kind of network, which database.
In the browser, you have no idea. It might be Internet Explorer 6 or Internet Explorer 10. It might be Chrome 26. Opera 16. Anything. You don't even know if your code is going to run in a browser or not. It might be a bot or some other kind of robot. So you have to be careful. Very careful.
Calling an API? Check for the existence of the API beforehand. Even something as basic as window.getComputedStyle is not supported by IE8. Heck, even calling indexOf() on an array didn't work until IE9.
However, this goes beyond APIs and runtime compatibility. People on different computers will have different setups. Different fonts installed. Different resolution. Different browser. Different visual acuity (and then, different zoom level on your site). Heck, let's go down the last mile: different tastes!
But you have to be reasonable. You cannot and will not and should not cater your website for every browser ever built. It would be impossible anyway. Keep in mind that the more you try to target, the more expensive it will be. As always, it will be a matter of setting the target where you feel it's best.
GUI vs Server - Unit testing dilemma
A program is judged by its I/O and usually nothing more. What is important is what you get in and what you get out of it.
A Server is usually getting things from a computer and spitting out to another computer. And computers love to talk to each other. As a result, building automated tests is possible and very rewarding.
Best practices for server side programming are now well established. Unit testing is at the core of them. Just because it's practical, useful and adds a very real value to your codebase.
Unit testing reduces drastically the risk of regressions whenever you modify a piece of existing code, and let's face it, we modify existing code all the time.
In the browser, you are building a User-Interface (UI). A UI is a computer getting things to a human. And building automated tests in a UI is much more complicated - at least if you target the same percentage of the functionality. As a result, manual testing becomes a much bigger part of the testing process.
Then you need to cater in the fact that your runtime environment is variable. Basically, you would need to run your tests in all runtime environments your code is susceptible to run on. Think IE, Firefox, WebKit, etc. That is harder but doable, since it is essentially a technical hurdle. Some frameworks do actually run browsers to do their testing, such as JsUnit, jsspec, Screw.unit, etc. Their setup is significantly more complex and restrictive than bare unit testing.
And last, you need to accommodate with the fact that you're testing a UI. How do you define your test as successful? Well... in the end, one thing matter: Is it usable and nice? And those criteria are exclusively human and very hard to program into an automated test. You're doomed and until human eyeballs report what they have seen on different configurations, you have no idea what they will see.
The bandwidth toll
On other hurdle that you rarely have to bother with on the server side (don't ask Google or Facebook) is bandwidth. A few years back this problem looked like it had vanished from the scene, but it never did, and for two reasons. First, the bandwidth alloted to our readers didn't just went up. It actually went down when people started to access sites on their mobile. Second, when you start considering that bandwidth is not a problem, it suddenly becomes one because you start overusing it.
Bandwidth is the ultimate dilemma. The more code you write, the lower your site responsiveness. Wanna load a library to speed things up? Guess what...
Studies show that the average attention span before a site loads is about 5s. That means that a majority of your users are going to go away after 5s of waiting for your site to load. And you're not one of them (that waits 5s). Because usually you do not access your website through the Internet so it is much faster for you. And even when you do, all your static resources are cached already on your browser. So for you, on most cases, your website loads much faster than the random user on the Internet.
The connectivity hazardLast but not least, and probably the least considered of the different problems, the fact that some of your resources will not be able to load. In other words, sometimes your page will have to work offline. With half the resources loaded. And that's another tough one.
Of course, nobody expects your website to work while no connectivity is available. It's more subtle than that. Let's take a simple example.
Now, you've decided that you're smarter than the browser and that you're going to intercept the button click with an onclick event handler. You then do an AJAX call and according to the result you will forward the user to the welcome page. To be extra-smart, you've decided to disable the button after one click. That takes care of those pesky users sometimes double-clicking. The scenario pans out like this: The user clicks on your button, the button disables itself, the AJAX request fails miserably because you're offline. The user is left with a page where the only button doing something is forever disabled.
Contrary to the popular belief, client side code is not harder to write than server-side code. In many ways, it's actually easier. What is harder is to make sure it works. For a variety of reasons. This makes client-side code a little more like craftmanship while the server-side code is a bit more like actual engineering. You will have noticed by now, I am fond of incredibly stupid analogies.
Complex client-side code is something incredibly powerful that can really change the user experience of your visitors. You just have to make sure it's a positive change because it can easily be the opposite.