Responsive Web Design with WURFL and NGINX Plus

Original: https://www.nginx.com/blog/responsive-web-design-with-wurfl-and-nginx-plus/

Responsive web design (RWD) has been around for some time, making it through the “hype cycle” and finding its way to the “plateau of productivity”. With RWD, web developers possess frameworks and guidelines on how to make their design adjust dynamically to the browser window and, to some extent, to the form factor of users’ devices.

However, all that glitters is not gold. Handling images in RWD has emerged as the major issue to address when website performance matters. In the case of classic one-size-fits-all image content, web developers are left with presenting a high‑resolution image to serve desktop, tablet, and smartphone users.

If you add to this the fact that those users may be accessing a site through a flaky mobile connection, you can imagine that this approach may result in a frustratingly slow user experience for a large portion of users. Not only are networks often slow, but pages with a large memory footprint also result in slow rendering and difficulty in scrolling – the device feels unresponsive as you try to interact with the service.

It’s not only the user who’s affected by slow page‑loading times. Google uses page‑loading times when determining search engine ranking. So long page‑loading times not only frustrate users when they get to your webpage – they might prevent users from getting to it in the first place!

Addressing Slow Page‑Loading Times

Initial approaches to mitigating slow page‑loading times were techniques such as polyfills, CSS hacks, and JavaScript libraries. A few years later, responsive images (the HTML <picture> tag) were introduced to address the same issue in a more standard way. Thanks to the <picture> tag, developers can provide references to multiple versions of an image and count on (recent) browsers picking the right one for the current browsing context.

Old browsers aside, here’s a typical scenario of how responsive images are served with the <picture> tag:

<picture>
  <source media="(min-width: 40em)" srcset="big.jpg 1x, big-hd.jpg 2x">
  <source srcset="small.jpg 1x, small-hd.jpg 2x">
  <img src="fallback.jpg" alt="">
</picture>

Old browsers default to fallback.jpg, but newer browsers can evaluate the browser context and request the image that makes the most sense. Readers of the NGINX blog may recognize this as the basis for a smart trick that enables NGINX to serve resized images with the Image‑Filter module.

Using the filter, you can specify the necessary sizes in the markup and, through configuration, we can have the image URLs piggyback the directives that the filter needs for the resizing.

The above technique is great, but it relies on several hefty assumptions about how the web content is organized and managed. For example, it assumes that the images are organized in files and that they have been placed in folders on the server. There are multiple reasons why this may not be not possible, particularly in large organizations, including:

For a site with these types of existing content, the <picture> tag isn’t the solution to the problem. At best, it can be regarded as a mechanism that redefines the problem. With responsive images, multi‑serving images is no longer a technical problem, but one of resources: you now need an editorial team that can select breakpoints, create different image versions, and manage an ever‑expanding library of image assets.

The challenge is that the images – that is, the correct version of each image – need to exist somewhere, be lightweight, and have good visual quality on all devices out there. But that’s not all. The Web is increasingly diverse. New devices might require new sizes or formats, while older formats and sizes may become obsolete over time. A bit of forward thinking may, at this point, be desirable.

Introducing ImageEngine from ScientiaMobile

This is where ScientiaMobile’s ImageEngine comes to the rescue. ImageEngine is a dynamic image‑optimizing content delivery network (CDN) with extra logic in the edge servers – that is, in the nodes that make up the CDN and that ensure proximity to client applications. Thanks to this edge logic, ImageEngine can optimize images for the size and properties of the requesting device.

More specifically, ImageEngine utilizes device detection to determine the optimal size and format for images based on a device’s screen size and properties. Device detection leverages a combination of the WURFL Device Description Repository and Client Hints. Together the two provide the best of both worlds by combining known device properties with properties that are known only at runtime, such as connection type or an indication that data should be saved.

For example, ImageEngine can compress more aggressively – creating lighter images, for example – for HTTP clients that access the service through a low‑bandwidth connection. While these optimizations happen in real time, the CDN ensures that images are cached close to the agents that may request them.

The use of WURFL allows ImageEngine to handle mobile traffic without additional responsive image HTML tags. WURFL also supplements Client Hints for browsers that do not support them.

In this blog post, we illustrate two scenarios in which NGINX Plus and ImageEngine can work together. The first scenario is a simple yet effective way to offload image serving to the ImageEngine CDN with a simple NGINX Plus configuration that rewrites the image URL. This scenario requires no further modules or additional software.

The second scenario is more advanced and relies on the WURFL InFuze Certified Module for NGINX Plus. In this more advanced scenario, WURFL supports the specific business model of an organization by relying on explicit ImageEngine directives.

A prerequisite for the first scenario is an ImageEngine license. The second scenario additionally requires the WURFL NGINX Plus Certified Module. You can request a free trial of both ImageEngine and the WURFL module at www.scientiamobile.com.

Scenario 1: Direct Image Requests to ImageEngine

In your NGINX or NGINX Plus configuration, you simply direct all your image requests to the unique ImageEngine hostname that you obtained during the ImageEngine account sign‑up procedure. In the examples below, we use try.imgeng.in as the hostname. This is a publicly available account for anyone who wants to try out ImageEngine.

When serving images through this hostname, all images are automatically be optimized for the requesting device or browser. However, try.imgeng.in has some limitations, so we recommend signing up for your own trial account to get the full functionality.

To redirect requests for several image types to ImageEngine, put this snippet in a server block:

location ~ .*\.(jpg|jpeg|gif|png|webp).*$ {
    if ($arg_optimize != no) {
        return 301 http://try.imgeng.in/http://$http_host$request_uri?optimize=no;
    }
}

When we include the optimize=no argument in the request URL, we get the unprocessed image:

<body>
    <h1>Redirect</h1>
    <p>Request for image below is redirected to imgeng.in for processing.</p>
    <img style="max-width: 100%" srcredu="ie1.jpg"/>
    <p>Request for image below is returned as is.</p>
    <img style="max-width: 100%" src="ie1.jpg?optimize=no"/>
</body>

With just this simple configuration change, users experience faster page loading. The effect of ImageEngine varies depending on the nature of the site, but the following results from a test help indicate the kind of improvement you’re likely to see. In the test we ran the ImageEngine demo tool against the outnorth.com ecommerce site.

The demo tool is based on the open source WebPagetest.org software and compares the performance of a website with and without ImageEngine optimization. The tool produces several interesting metrics to look at:

Scenario 2: Exploit WURFL to Fine‑Tune Images with Custom Logic

As explained, by default ImageEngine uses Client Hints and device information to decide how to optimize a picture. But this is not the only way to use the tool. ImageEngine can also take explicit directives that instruct it on how to treat each image. While not all directives disable the device detection function in ImageEngine, most do. Directives are essentially a way to tell ImageEngine that the programmer knows what he or she is doing and wants to override ImageEngine’s built‑in intelligence for resizing.

Directives can dictate compression rate, format, height, width, cropping, fitting, and other features of the image. ImageEngine handles most aspects of optimizing the image automatically, but some directives are useful when designing a site.

Directives are passed to ImageEngine with query string parameters. For example, you may want to specify the exact width and the height of the image in the URL that retrieves the image. In this specific case, the image returned is 800 pixels wide and 500 pixels high.

try.imgeng.in/http://example.com/img.png?imgeng=/w_800/h_500

Once you lock the image size this way, all devices and browsers get the same image regardless of their properties. That’s unless you can support your own device intelligence, which is exactly what NGINX Plus users can do with the InFuze WURFL Module. The InFuze WURFL Module augments NGINX Plus with device‑detection capabilities. Those capabilities can be used to create URLs containing directives that change on a per‑device basis.

Note: For installation instructions, see the InFuze NGINX Module User Guide.

Here’s a sample NGINX Plus configuration snippet that shows how HTTP requests can be enriched with additional device information:

http {
    wurfl_enable    on;
    # -- WURFL Data file load
    wurfl_root      /usr/share/wurfl/wurfl.zip;

    # Increase the variable hash size
    variables_hash_max_size 1024;
    variables_hash_bucket_size 1024;

    # -- WURFL cache: uncomment one of the following
    #wurfl_cache_null;
    wurfl_cache_double_lru 100000,30000;

    # -- WURFL user-requested static capabilities (this is not a complete list)
    wurfl_request_capability resolution_width;
    wurfl_request_capability resolution_height;
}

This configuration makes the resolution_width and resolution_height characteristics of the requesting device available in the NGINX Plus $resolution_width and $resolution_height variables respectively. These variables can be leveraged to instruct ImageEngine to serve images whose size conforms to the screen size of the requesting device.

try.imgeng.in/http://examle.com/img.png?imgeng=/w_$wurfl_cap_resolution_width/h_$wurfl_cap_resolution_height/

We need NGINX Plus to dynamically perform this translation. We can also use this step to make URLs prettier through URL rewriting. In the process, we would also like to remove references to imgeng.in so that we can refer to images with URLs as simple as:

//images.example.com/img.png

The following NGINX Plus configuration is an example of passing a resolution image to the imgen.in service and rewriting the URLs. This configuration snippet can be added to an existing .conf file in /etc/nginx/conf.d as part of a larger server block.

location ~ .*\.(jpg|jpeg|gif|png|webp).*$ {
  if ($arg_optimize != no) {
     return 301 http://try.imgeng.in/w_$wurfl_cap_resolution_width/h_$wurfl_cap_resolution_height/http://$http_host$request_uri?optimize=no;
  }
}

This setup makes sure that images are never larger than the resolution width of the screen, which might be useful, for example, in the case of hero images or images used for background.

WURFL is not only about device screen size – it also contains a variety of other properties that can be leveraged for other types of optimization, for Ad Tech, and for Analytics.

Summary

This post has discussed the benefit of server‑side device optimization for the purpose of minimizing the payloads of web pages accessed through mobile devices.

We’ve shown how device detection can be used to implement custom policies for resizing and optimizing images in an RWD context. It’s worth noting that these are just sample scenarios in which device detection can be deployed. Several others are possible. The WURFL Certified Module for NGINX Plus can be used to create scaled‑down, snappy versions of your content for smartphones, or even feature phones.

Augmenting HTTP requests with device information is a simple strategy to optimize user experience based on the form factor of the device and HTTP client. Depending on what service you offer, you may want desktop users, tablet users, and smart TVs to navigate your site differently. Device detection can help you segment your offering in ways that better fit your organization or your business model.

ScientiaMobile’s ImageEngine is a great starting point that offers benefits out of the box, but NGINX Plus users can also benefit from adopting the InFuze WURFL Certified Module for NGINX Plus.

The WURFL module enriches NGINX Plus and enables new policies based on the actual features of different HTTP clients. We have shown a scenario in which the WURFL Certified Module for NGINX Plus works with ImageEngine to implement customized policies for image optimization and improve the user experience.

While the image‑optimization use case is pretty compelling, we’ve also mentioned that device detection has a variety of other uses, particularly when used in connection with the powerful NGINX Plus machinery.

You can try the WURFL InFuze Certified Module for free for 30 days.

To try NGINX Plus, start your free 30‑day trial today or contact NGINX for a demo.

Retrieved by Nick Shadrin from nginx.com website.