Performance best practices

If you are reading this book, it is probably because you are interested in web development and, in the last few years, the importance of the performance of web applications (such as APIs) is becoming more and more relevant. Here are some stats to give you an idea:

  • Amazon reported years ago that for every 100 ms of increase in the loading time, their sales decreased by 1%.
  • Google found that reducing the size of the page from 100 KB to 80 KB diminished their traffic by 25%.
  • 57% of online consumers will abandon a site after waiting for 3 seconds for a page to load.
  • 80% of the people who abandoned the site will not return. About a 50% of these people will tell others their negative experience.

As you can see, the performance of your app can impact your users and even your revenues. In this section, we will give you some tips to improve the overall performance of your web application.

Minimize HTTP requests

Each HTTP request has a payload. For this reason, an easy way to increase the performance is to reduce the number of HTTP requests. You need to have this idea in mind in every aspect of your development. Try to do the minimum external calls to other services in your APIs/backends. In your frontends, you can combine files to attend to only one request. You only need to have a balance between the number of requests and the size of each request.

Imagine that your frontend has its CSS split in several different files; instead of loading each one every time, you can combine them into a single or a few files.

Another quick and small change you can do with HTTP requests is to try to avoid @import functions in your CSS files. Using link tags instead of @import functions will allow your browser to download the CSS file in parallel.

Minimize HTML, CSS, and JavaScript

As developers, we try to code in a format that is easier for us to read--a human-friendly format. By developing this way, we are increasing the size of our plain text files with unnecessary characters. Unnecessary characters can include white space, comments, and newline characters.

We are not saying that you need to write obfuscated code, but as soon as you have everything ready, why don't you remove the inessential characters?

Imagine that the content of one of your JavaScript file (myapp.js) is as follows:

    /**
    * This is my JS APP
    */
    var myApp = {
      // My app variable
      myVariable : 'value1',

      // Main action of my JS app
      doSomething : function () {
        alert('Doing stuff');
      }
    };

After the minimization, your code can be saved to a different file (myapp.min.js) and it can look as follows:

    var myApp={myVariable:"value1",doSomething:function()
      {alert("Doing stuff")}};

In the new code, we reduced the size of the file around 60%, a huge saving. Note that our repository will have both versions of the file: the human-friendly to make our changes, and the minimized one, which we will load in our frontend.

You can do the minimization with online tools, or you can integrate tools such as gulp or grunt in your pipeline. When you have set up these tools, they will track the changes of some specific files (CSS, JS, and others) and as soon as you save your changes to any of these files, the tool will minimize the content. Another hidden benefit of using tools for the minification is that most of them also check the code or rename your variables to keep them even smaller.

Image optimization

One of the most used assets in web development can be the images. They make your website look amazing, but they can make your site painfully slow. The main recommendation is to keep the number of images to the minimum, but if you need to keep images, at least try to optimize them before they are sent to your users. In this section, we will show you some things you can do to optimize your images and, as a consequence, the performance of your application.

Use sprites

A sprite is an image composed by multiple images; later, you can use this image and show only the portion you are interested in. Imagine that you have a nice website and, on each page, you have some social icons (Facebook, Twitter, Instagram, and so on). Instead of having one image for each social icon, you can combine them in one and use CSS to show only the part you want for each icon. Doing this, you will have all the social icons with only one load, reducing the number of requests.

Our recommendation is to keep your sprites small and include only the most used and shared images in them.

Use lossless image compression

Not all image formats are suitable for the Web as some formats are either too big or do not support compression. The three most used image types on the Web nowadays are as listed:

  • JPG: This is one of the most commonly used method of lossless compression
  • PNG: This is the best format with lossless data compression
  • GIF: This is an old-school format that supports up to 8 bits per pixel for each image and is well known for its animated effects

The recommended format for the web at this moment is PNG. It is well supported by the browsers, easy to create, supports compression, and gives you all the power you need to improve the performance of your site to the maximum.

Scale your images

If you are using images and not data URIs, they should be sent at their original size. You should avoid resizing your images using CSS and send the image with the correct size to the browser. The only case when it is recommended to scale images by CSS is with fluid images (responsive design).

You can scale your images easily with PHP libraries like Imagick or GD. With these libraries and a few lines of code, you can scale your images in seconds. Usually, you do not scale the images on the fly. Most of the time, as soon as an image is uploaded to your application, a batch process takes care of the image, creating the different sizes needed by your application.

Imagine that you can upload images of any size to your application and you only show images with a maximum width of 350px in your frontend. You can easily scale the previously stored image with Imagick:

    $imagePath = '/tmp/my_uploaded_image.png';
    $myImage   = new Imagick($imagePath);

    $myImage->resizeImage(350, 0, Imagick::FILTER_LANCZOS, 1);

    $myImage->writeImage('/tmp/my_uploaded_image_350.png');

The preceding code will load the my_uploaded_image.png file and resize the image to a width of 350px using the Lanczos filter (refer to the PHP Imagick documentation to see all the available filters you can use).

That's one way of doing it, another (and maybe even more effective) common way is to resize images on demand (that is, when first requested from client side), and then store the resized image either in cache or permanent storage.

Use data URIs

Another quick way of reducing the number of HTTP requests is embedding images as data URIs. This way, you will have the image as a string inside your code avoiding the request of the image, this method is the best fit for static pages. The best way to generate this kind of URIs is with external or online tools.

The following example will show you how it will look in your HTML:

    <img src="data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEAYABgA..."
     alt="My Image">

Cache, cache, and more cache

Performance on the Web is all about serving data as fast as possible and, if our application already sent data that continues to be valid, why send it again? By default, modern browsers try to reduce the number of requests they make to the same site, so they keep a copy of some assets/resources in their internal cache for their future use. Thanks to this behavior, if you are browsing a website, we are not trying to load all the assets again and again as soon as you move between sections.

You can help your browser in specifying each request response with the following Cache-Control HTTP headers:

  • max-age=[seconds]: This sets the maximum amount of time that a response will be considered fresh. This directive is relative to the time of the request.
  • s-maxage=[seconds]: This is similar to max-age, but for shared caches.
  • public: This tag marks the response as cacheable.
  • private: This tag allows you to store the response to one user. Shared caches are not allowed to store the response.
  • no-cache: This tag instructs caches to submit the request to the original server for validation.
  • no-store: This tag instructs caches not to keep a copy of the response.
  • must-revalidate: This tag tells the caches that they must follow any fresh information you give them about a response.
  • proxy-revalidate: This is similar to must-revalidate, but for proxy caches.

The main recommendation is to tag static assets with an expiration of at least one week or one day on long-life assets. In the case of assets that change frequently, the recommendation is to set the expiration to a couple of days or less. Adjust the cache expiration dates of your assets according to their life.

Imagine that you have one image that changes every 6 hours; in this case, you should not set the expiration date to a week, the best choice will be around 6 hours.

Avoid bad requests

There is nothing more annoying than bad requests as this kind of requests can reduce the performance of your application drastically. As you probably know, the browsers have a limited number of concurrent connections that they can manage at the same time for the same host. If your website makes a lot of requests, this list of available slots for connections can be full and the remaining requests are queued.

Imagine that your browser can manage up to 10 concurrent connections and your web application makes 20 requests. Not all the requests can be attended to at the same time and some of them are queued. What happens now if your application is trying to get an asset and it does not exist? In this case, the browser will waste its time (and slot) waiting for the non-existent asset to be served, but it will never happen.

As a recommendation, keep an eye on your browser developer tools (a set of web debugging tools built into the browsers you can use to debug and profile your site). These tools allow you to spot problematic requests and you can even check the amount of time used on each request. In most of the browsers, you can open the embedded developer tools pressing the F12 key but, if your browser do not open the tools on pressing this key, check the browser's documentation.

Use Content Delivery Networks (CDNs)

A content delivery network hosts a copy of your assets in servers designed to respond quickly and from the closest server possible. That way, if you are moving the requests from your servers to the CDN servers, your web servers will be dealing with fewer requests, improving the performance of your application.

Imagine that you use jQuery in your frontend; if you change your code to load the library from an official CDN, the probability of an user having the library in their browser cache increases.

Our main recommendation is to use CDNs at least for your CSS, JavaScript, and images.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.147.42.163