A brief overview of responsibilities in modern web development

As many of us experienced, the world of web development got more complex in the last couple of years. Especially for newcomers it's somewhat difficult to get through all the different layers. Everybody needs to know plenty of frameworks and it seems like every job description wants something different. That's why it's a good idea to learn and internalize some fundamentals. Today, I want to write about responsibilities in modern web applications.

What has changed in modern web development

As I wrote in the introduction, the web development world became more and more complex in the last decade. When we look back at the early 2000s, we had something like PHP, JSF / JSP or ASP which all fundamentally worked in way, that you define your html flavoured with server code so that you could retrieve data from a database and implement business logic on the server.

With the rising of cloud computing and the necissity to provide APIs on one side and more and more calculation power on even the smallest wearable on the other side, the "server-only" approach was no longer necessary nor desirable. That's where the time of SPA's (Single Page Applications) began. Now people could write a complete application, download it from the server and keep it in the RAM for the whole lifecyle, which made the pages much more responsive (as they only had to download volatile data) and even opened the ability to make pages available offline (e.g. in form of PWAs - Progressive Web Apps). This of course comes with a price: Higher complexity in our web application.

Where we had all the logic in a page that only lasted for the time the request was done, our recent "Pages" became real applications - deployed in HTML, JavaScript and CSS. This of course introduces complexity that we have to handle as programmers. That's why we need to come up with a structure to organize things properly to make it maintanable. From looking at the most popular framework composition, it looks like there are some best practises that have been very well established:

The "View"

It doesn't matter if you chose React, Vue or Angular: The view part is the minimum every framework tackles. While there are different approaches, the core of all of them is to provide the ability to structure your web application into components, that are reusable. Those components are build on three pillars: HTML, JavaScript and CSS. Of course, some of them use TypeScript, CoffeeScript or Dart (which all compiles to JavaScript) and some of them support SCSS or SASS, but it all transpiles down to those three.

In a perfectly written application, the view part would be exchangeable without too much effort (although we all know, that no one writes perfect code 😁).

The "ViewModel"

The ViewModel is like the "glue" between the actual business logic and the view. It oftenly works like a proxy for the services or stores with "translation" capabilities. So for example, it's perfectly fine if the service returns "1000" and "EUR", that the view model will alter the data to "1.000 €" before forwarding it to the "view". The approaches are as different, as the frameworks are:

  • Angular quite a large destinction between the View (html) and the ViewModel (typescript component)
  • Vue has both, View and ViewModel from the beginning in one file, because one cannot exist without the other and if you modfiy one, you probably have to modify the other too
  • React is a bit special: From my limited experience, it has no integrated concept of a viewmodel, but rather a more functional re-rendering approach. You might still add some ViewModel if you want to, but you have to implement it yourself.

Show me the way, "Router"!

As we talked about implementing "Single Page Applications" (SPAs), the router has the responsibility to "route" the requests of the user. This is in general done in one of those two ways:

The "Hashbang" method

The "Hashbang" approach is a simple but great approach to do SPA routing. Every page is able to add any content after adding a hashtag to the corresponding site, because that's in the "original way of thinking" an anchor on my current page. If the anchor doesn't exist, the browser won't do anything with it. However, the frameworks are able to retrieve the anchor with javascript and parse them, so that it looks like you are on a "real" page. So for example:

example.com/index.html#/foo/bar

is a normal request to index.html. However, if we would read the anchor with javascript, it would read "/foo/bar" and this is exactly how the router resolves the requested page.

The "History" mode

As a prerequisite for the History mode, we need to have a webserver configured to forward all requests that are not index.html to our index.html. So if we want to access

example.com/foo/bar

our server sees, that "/foo/bar" does not exist and forwards the request to our index.html. Now the router is able to look into the History, where we came from and routes the user to the designated location. This mode is a bit more complex to configure, but more appealing to a user, because it feels more like a "real" website.

What about our Frameworks?

  • Angular has integrated routing
  • Vue and React don't have an integrated router, but there are additional modules available for both of them

About "Services"

I like to think of services in web development as "Gates to the outside world". They handle the "heavy stuff" - make ajax calls, transform data (e.g. files into base64 strings) or provide other "services" that are needed by your application. Services may contain business logic and depending on your architecture even be responsible for caching mechanisms.

  • if you learn Angular, it will provide you with some (opinionated) approach on how to structure your services and how to access them (dependency injection)
  • Vue and react don't enforce any specific concepts - you have to come up with something on your own (although of course plenty of tutorials with best practises exist)

What a "State Management" does

The idea of state management is as simple as great: As our web applications should be deterministic, we could basically assume that if we put in the same data (state), we will get out the exact same result. As for this, it makes sense to have a state that is global and immutable (we don't alter states, we replace them with a new "version").

Most of the State Management Systems work with "Events" (e.g. Observable pattern) or reactivity (e.g. TFRP - Transparent Functional Reactive Programming). The store could also implement caching mechanisms. Every framework is able to "add" some state management if you don't want to implement it yourself.

An incomplete list of commonly used state management frameworks:

  • Angular: ngrx, ngxs, mobx
  • React: mobx, redux
  • Vue: vuex, mobx, redux

I hope you liked the overview of different responsibilities in modern web development. I will guide you deeper into those topics in a future article series about Web Development Fundamentals.