Sustainable backend web development
May 06, 2022
Anyone who operates a web presence nowadays usually does so with the help of a content management system. This CMS provides the backend and often also the frontend of a professional website. Compared to static websites, CMSs offer the charming advantage that the operator can easily and comfortably edit and create new content. This gives editors easy means to create content, but of course also leads to an increased load on the servers: Content is not simply output in the form of static HTML, but is first loaded from a database, then processed, and finally delivered as HTML to the viewer’s browser. This naturally increases the load on the server, since these processes are much more complex than delivering static HTML.
Why are we dealing with the topic of sustainable web development? We want to make the web more sustainable and greener, because as a company in the IT sector we have a certain responsibility towards climate change. We want to meet this responsibility by thinking about sustainability in web development.
Green IT in backend: What can we do?
When we think about how to run a website greener, we should definitely also look at the backend of the website. This includes the server-side components such as communication with the database and rendering of the HTML to be delivered. Generally speaking, the rule of thumb here is “the better a website performs, the greener it is”. Because, of course, a fast website also uses proportionally less of the server from which it is provided. So we can reduce the load on the web server by optimizing it and thus save power.
The reduction of resource consumption can be achieved in the backend in various ways. In the following, we give an overview of various techniques and tools. We pay special attention to the CMS Drupal, which is used for many of our web projects.
A powerful tool in performance enhancement is caching. Content is cached and delivered as needed. Caches exist in various places. Many users are familiar with the browser cache. This stores images on the client side, for example, so that the images can be delivered locally when the page is called up again instead of having to download them. There are also server-side caches. If content is changed infrequently or predictably often, a server-side cache helps to store pages, or just parts of pages. Instead of having to query all data from the database, the cache is queried and delivers the ready prepared and rendered content. Here, of course, the concrete implementations differ depending on the system used.
Drupal has caching mechanisms built directly into the core. The cache has a maximum lifetime, which indicates how long a cache entry is durable and thus remains valid and applicable. If one can assume that content changes only rarely, a high cache lifetime can ensure that the load on the server and database is reduced enormously. Especially for anonymous users who have not logged in to the site, this can increase performance enormously. This is because guest users of a website usually all see the same content, without personalized components. So in this case the website can be cached once and delivered again and again.
Drupal’s cache offers through the use of cache tags and cache contexts the possibility to define fine-grained which criteria should be used to build a cache. You determine on which data this cache is dependent. If, for example, a certain cache entry is dependent on various contents, it is rebuilt as soon as one of the dependent contents changes. This way, even dynamic content can benefit from caching without being delivered in an invalid state.
In this example implementation we see how in Drupal the caching of a content can be set depending on a configuration value. Once this value changes, the block’s cache is invalidated and re-rendered and cached when requested again.
Also, Drupal can cache dynamic lists created using the Views module and keep them cached for a specified duration. This is very useful, as Views in particular create a heavy load on the database when aggregating the necessary content.
Drupal’s cache is even able to work with placeholders. If only a small part of a page is highly dynamic and changes often, placeholders are a useful tool. They allow developers to use caching despite the dynamic part of the page. The small dynamic part is then left out of the cache and reinserted using a placeholder after loading from the cache.
If you want to learn more about caching, I recommend the session of my colleague Kristiaan van den Eynde at DrupalCon 2019 in Amsterdam, where he provides an introduction to the use of the cache systems available in Drupal 8:
Responsive images & image optimizations
Nowadays, a website is rarely viewed on a desktop computer. The landscape of different Internet-enabled devices is becoming more diverse, making their consideration in web development more relevant. Mobile first is now the industry standard. But even beyond that, websites can be optimized for mobile devices and thus accelerated.
For example, images can be delivered in a resolution suitable for the smaller screen of a smartphone or tablet. By specifying a whole list of image sources with the associated media queries instead of just one, the client can choose the appropriate image variant itself. This saves bandwidth by not having to load images that are too large to display at full size anyway.
HTML already provides the foundation for this with the srcset attribute of the image tag and the source tags within a picture tag: We are able to specify different image sources for different resolutions and thus ensure that users do not have to download unnecessarily large images for small screens, but still have HiRes versions available for large viewports.
In practice, this looks something like this:
The client selects from the given derivatives the version that fits the resolution used.
Besides, it is worth using modern image formats like .webp. The compression is good and the resulting files are smaller than their equivalents in .png or .jpeg. Even though not all browsers (Looking at you, IE) support .webp yet, using the srcset attribute of HTML described above helps us out here again. If you specify .webp files as one of the image sources, the browser will choose it if it can. If it is not, alternative versions are used. By using multiple source elements with the same media query, we can provide alternatives here.
Drupal already has the image styles and responsive image modules in core. By using the modules, editors can upload images to the system. These are automatically cropped to configured image sizes and rendered using responsive images to deliver the best possible image variant for the viewport used. If you add the webp module from the Drupal community, you have a solution that displays responsive images out of the box as webp.
And while we’re on the subject of optimizing images, it’s also worth thinking about lazy loading. With this no longer quite young technique, images are only loaded when they actually become visible for the current viewport. This saves requests and increases performance when many images are displayed on a page. For Drupal there is a module called Blazy that provides exactly this technique.
A website can be further accelerated by using a content delivery network (CDN). In this case, a third-party provider is used to deliver resources and provides specialized servers for this purpose. If a CDN is used, the latency time for accessing resources is reduced: an independent network of caching servers distributed over geographically sensible locations ensures that content only has to cover the shortest possible routes for delivery. This reduces the energy consumption of the network infrastructure and speeds up the delivery of resources. Drupal offers connections to various CDNs through the use of modules, which can be used for resources within your Drupal installation.
Aggregate and minimize JS and CSS
Reduction of the productive system
Drupal 8 has the ability to use different configurations for different environments of a website. For example, a staging or test environment may have a different underlying configuration than the production environment. The configuration contains virtually all the mutable data necessary for Drupal to function.
We can increase Drupal’s performance (albeit only a little in newer versions) by disabling modules in the production system that don’t serve any purpose there anyway. For example, Drupal provides a powerful tool through Views to configure dynamic lists of content and display them in the form of pages or content blocks in the website. Additionally, there is the ViewsUI module, the user interface for views. This can be used to create views, which is handy in the development process. However, the module is not necessary for displaying a view. On professional sites with connected deployment processes it has no use anyway, because changes are only made in local development environments. So you can deactivate certain modules in the production environment, which are not needed there. Because the mere fact that a module is activated worsens the performance of the page. For each individual module, however, it should be clearly weighed up whether it is actually useless in the productive system.
Optimized source code
In all our own developments, we should make sure that we optimize our code. For many developers this may sound banal, but it is no less important! If we optimize our source code and, for example, save unnecessary function calls and store intermediate results instead of performing calculations over and over again, we save valuable computing time during calculations and operations. The resulting energy savings for a heavily used website or web service quickly add up to an impressive amount.
Want an example? Here’s one of my favorite beginner mistakes from the Drupal world:
This code is supposed to do things with content that meets certain criteria. The example criteria here are the content type (= basic_page) and the value in the field field_my_field (= foo). The code will work and do what it is supposed to. However, we load more content than necessary to check if the criteria are met.
We can avoid this by using a custom entity query:
Instead of loading nodes and then examining them, we load only those that actually match the criteria. Also, if we need to examine more complex criteria and look at fields of a referenced sub-entity, for example, we do not need to load the node to access the fields of the referenced entity. Instead, this condition can also be formulated using the entity query:
Formulating a complex entity query is much more performant than manually loading and checking the entities. In some cases, it may also make sense to use a static query or a dynamic query to further improve performance. If you want to know exactly where in the code unimagined, performance-eating bottlenecks are hiding, I also recommend the profiler of XDebug, which helps to identify and fix exactly these.
There are various approaches to make a backend greener. The approaches listed here are only a fraction of the possibilities. You may be asking yourself, “How am I supposed to sell this to my clients?” Quite simply, every optimization that contributes to the account of green web development also offers another added value: increased performance and thus a higher speed of the website. And we web developers know how important it is to take performance optimization seriously. Google likes performant pages; we increase the SEO ranking. Users like performant pages; we lower the bounce rate and potentially increase the conversion rate.
Sustainability in web development is therefore not synonymous with additional costs. On the contrary, a website optimized for sustainability can increase its success and also the revenue it generates. So if it is not the intention of a web project to contribute to saving our planet, it is certainly the intention to make the end product as promising as possible. The account we are paying into is the same. Only the points of view differ.