In this chapter, we will cover:
Preventing mobile transcoding
Adding mobile MIME types
Making cache manifest display properly
Setting far future expire headers
Gzip compression
Entity tag removal
Server-side performance directly impacts the page loading speed. Proper server configuration can hugely improve the client-side loading speed.
In this chapter, we will go through some of the server-side configurations used to make mobile websites and applications perform better and faster. Some of the concepts are mobile-centric; some are applicable to the desktop web as well.
There are many server best practice guidelines, but some may not be comprehensive enough. In this chapter, we combine the best of the best practices and see how we can maximize the performance of a site.
Target browsers: cross-browser
Many mobile operators use proxies or adaptation engines to change the content of the web page you want to serve. On many mobile devices, built-in or installed browsers use mobile transcoders to reformat and compress page content. This is called Mobile Transcoding. If you don't want the content to be altered, an HTTP header must be added to prevent mobile transcoding.
An .htaccess
file is used to configure an Apache server at the file directory level. The configuration can also be done by editing httpd.conf
. Because many server hosting companies won't allow access to the root where the Apache is installed, in this example, we use .htaccess
. This makes the server configuration at a directory level easier because unlike main httpd.conf
, it doesn't require the server to be restarted. Create or open an .htaccess
file.
Add the following code to the .htaccess
file:
<FilesMatch ".(php|cgi|pl)$"> Header append Cache-Control "no-transform" Header append Vary "User-Agent, Accept" </FilesMatch>
Upload the .htaccess
file to the folder to which you want the rules to apply.
By doing this, we have prevented mobile transcoding from happening.
FilesMatch
is used to filter only CGI and PHP scripts, because we don't want to apply this rule to other file types.
<FilesMatch ".(php|cgi|pl)$">
Provided that Apache module mod_headers
is enabled, we can add the header Cache-Control "no-transform"
in a FilesMatch
section.
Header append Cache-Control "no-transform"
The following resources might be helpful in knowing more about mobile transcoding.
If you are using Microsoft Internet Information Server (IIS), it can be configured using the software interface. Details about how to do this can be found at:
http://mobiforge.com/developing/story/setting-http-headers-advise-transcoding-proxies
The following article provides some insights about the impact of content transcoding done by network operators:
http://mobiforge.com/developing/blog/responsible-reformatting
The snippet used in this chapter is also included in Mobile Boilerplate:
https://github.com/h5bp/mobile-boilerplate/blob/master/.htaccess
Target browsers: Blackberry, Symbian
There are many mobile-exclusive content types supported by BlackBerry and Nokia browsers. In this topic, we will look at some of the MIME types used by these mobile browsers. As the server might not recognize them by default, it is important to add them correctly in the server configuration.
An .htaccess
file is used to configure the Apache server at the file directory level. It makes the server configuration at directory level easy. Create or open an .htaccess
file.
Add the following code to the .htaccess
file:
AddType application/x-bb-appworld bbaw AddType text/vnd.rim.location.xloc xloc AddType text/x-vcard vcf AddType application/octet-stream sisx AddType application/vnd.symbian.install sis
Upload the .htaccess
file to the folder at which you want the rules to apply.
We make the mobile MIME types recognizable by using AddType:
Code |
Description |
---|---|
|
A text file that contains the application ID for an application found in the BlackBerry App World™ storefront. |
|
A BlackBerry Maps location document. |
|
A vCard file, a standard file format for electronic business cards. |
|
Nokia types |
|
Nokia types |
For more mobile file types supported by BlackBerry, go to:
Target browsers: cross-browser
As explained in Chapter 6, Mobile Rich Media, cache manifest is used for offline web applications. The extensions for this file may not be recognized by the server. Let's see how we can add the proper MIME type.
Add the following code:
AddType text/cache-manifest appcache manifest
Upload the .htaccess
file to the folder you want the rules to apply.
Cache manifest may have either .appcache
or .manifest
as its extension. By adding both types as text/cache-manifest
, we are making sure they can both be rendered correctly regardless of which one is used.
The .htaccess
rule is included in the Mobile Boilerplate:
https://github.com/h5bp/mobile-boilerplate/blob/master/.htaccess#L75
Target browsers: cross-browser
Setting up far future expire headers for files is used to improve site performance by reducing unnecessary HTTP requests. For a rich media site with many resources to load, this can improve the overall performance. There are different file types and, depending on the use of the file, we choose different periods of time for them to expire.
Add the following code:
<IfModule mod_expires.c> ExpiresActive on ExpiresDefault "access plus 1 month" ExpiresByType text/cache-manifest "access plus 0 seconds" ExpiresByType text/html "access plus 0 seconds" ExpiresByType text/xml "access plus 0 seconds" ExpiresByType application/xml "access plus 0 seconds" ExpiresByType application/json "access plus 0 seconds" ExpiresByType application/rss+xml "access plus 1 hour" ExpiresByType image/x-icon "access plus 1 week" ExpiresByType image/gif "access plus 1 month" ExpiresByType image/png "access plus 1 month" ExpiresByType image/jpg "access plus 1 month" ExpiresByType image/jpeg "access plus 1 month" ExpiresByType video/ogg "access plus 1 month" ExpiresByType audio/ogg "access plus 1 month" ExpiresByType video/mp4 "access plus 1 month" ExpiresByType video/webm "access plus 1 month" ExpiresByType text/x-component "access plus 1 month" ExpiresByType font/truetype "access plus 1 month" ExpiresByType font/opentype "access plus 1 month" ExpiresByType application/x-font-woff "access plus 1 month" ExpiresByType image/svg+xml "access plus 1 month" ExpiresByType application/vnd.ms-fontobject "access plus 1 month" ExpiresByType text/css "access plus 1 year" ExpiresByType application/javascript "access plus 1 year" ExpiresByType text/javascript "access plus 1 year" <IfModule mod_headers.c> Header append Cache-Control "public" </IfModule> </IfModule>
Upload the .htaccess
file to the folder to which you want the rules to apply.
Here is the breakdown of the code where we will see how it works:
Whitelist Expires rules:
ExpiresDefault "access plus 1 month"
cache.appcache
needs re-requests in FF 3.6:
ExpiresByType text/cache-manifest "access plus 0 seconds"
Your document HTML shouldn't be cached:
ExpiresByType text/html "access plus 0 seconds"
Data shouldn't be cached as it always needs to be pulled:
ExpiresByType text/xml "access plus 0 seconds" ExpiresByType application/xml "access plus 0 seconds" ExpiresByType application/json "access plus 0 seconds"
RSS feed updates less frequently than normal API data:
ExpiresByType application/rss+xml "access plus 1 hour"
Favicon cannot be renamed, so the best approach is to set it to a week from now:
ExpiresByType image/x-icon "access plus 1 week"
For heavy media resources such as images, video, and audio, we can set the date further in the future:
ExpiresByType image/gif "access plus 1 month" ... ExpiresByType video/webm "access plus 1 month"
HTC files, useful if you use HTML5 polyfill - CSS3PIE:
ExpiresByType text/x-component "access plus 1 month"
It's safe to cache Webfonts for a month:
ExpiresByType font/truetype "access plus 1 month" ... ExpiresByType application/vnd.ms-fontobject "access plus 1 month"
For CSS and JavaScript, we can set the expiration date to be a year ahead:
ExpiresByType text/css "access plus 1 year" ExpiresByType application/javascript "access plus 1 year" ExpiresByType text/javascript "access plus 1 year"
These are pretty far-future Expires headers. They assume you control versioning with cache busting query parameters such as:
<script src="script_034543.js" ></script>
Additionally, consider the possibility that outdated proxies may miscache:
http://www.stevesouders.com/blog/2008/08/23/revving-filenames-dont-use-querystring/
These rules are included in Mobile Boilerplate's .htacess file:
https://github.com/h5bp/mobile-boilerplate/blob/master/.htaccess#L142
Target browsers: cross-browser
Frontend developers play an important role in making decisions about how to reduce the time it takes to transfer HTTP requests and responses across the network. Gzip compression can be used to reduce response time by reducing the size of the HTTP response.
Gzip drastically reduces the response size, usually by 70 percent. Gzip is widely supported by modern browsers.
Most servers only compress certain file types by default, so it's best to define rules that support a wide range of text files, including HTML, XML, and JSON.
Add the following code in to .htaccess:
<IfModule mod_deflate.c> <IfModule mod_setenvif.c> <IfModule mod_headers.c> SetEnvIfNoCase ^(Accept-EncodXng|X-cept-Encoding|X{15}|~{15}|-{15})$ ^((gzip|deflate)s,?s(gzip|deflate)?|X{4,13}|~{4,13}|-{4,13})$ HAVE_Accept-Encoding RequestHeader append Accept-Encoding "gzip,deflate" env=HAVE_Accept-Encoding </IfModule> </IfModule> <IfModule filter_module> FilterDeclare COMPRESS FilterProvider COMPRESS DEFLATE resp=Content-Type $text/html FilterProvider COMPRESS DEFLATE resp=Content-Type $text/css FilterProvider COMPRESS DEFLATE resp=Content-Type $text/javascript FilterProvider COMPRESS DEFLATE resp=Content-Type $text/plain FilterProvider COMPRESS DEFLATE resp=Content-Type $text/xml FilterProvider COMPRESS DEFLATE resp=Content-Type $text/x-component FilterProvider COMPRESS DEFLATE resp=Content-Type $application/javascript FilterProvider COMPRESS DEFLATE resp=Content-Type $application/json FilterProvider COMPRESS DEFLATE resp=Content-Type $application/xml FilterProvider COMPRESS DEFLATE resp=Content-Type $application/x-javascript FilterProvider COMPRESS DEFLATE resp=Content-Type $application/xhtml+xml FilterProvider COMPRESS DEFLATE resp=Content-Type $application/rss+xml FilterProvider COMPRESS DEFLATE resp=Content-Type $application/atom+xml FilterProvider COMPRESS DEFLATE resp=Content-Type $application/vnd.ms-fontobject FilterProvider COMPRESS DEFLATE resp=Content-Type $image/svg+xml FilterProvider COMPRESS DEFLATE resp=Content-Type $application/x-font-ttf FilterProvider COMPRESS DEFLATE resp=Content-Type $font/opentype FilterChain COMPRESS FilterProtocol COMPRESS DEFLATE change=yes;byteranges=no </IfModule> <IfModule !mod_filter.c> AddOutputFilterByType DEFLATE text/html text/plain text/css application/json AddOutputFilterByType DEFLATE text/javascript application/javascript application/x-javascript AddOutputFilterByType DEFLATE text/xml application/xml text/x-component AddOutputFilterByType DEFLATE application/xhtml+xml application/rss+xml application/atom+xml AddOutputFilterByType DEFLATE image/svg+xml application/vnd.ms-fontobject application/x-font-ttf font/opentype </IfModule> </IfModule>
Upload the .htaccess
file to the folder to which you want the rules to apply.
The following code forces deflation for mangled headers, in order to detect the mangled patterns, mod_setenvif
is used to perform a regular expression match and set an environment variable indicating the mangled Accept-Encoding header is present:
SetEnvIfNoCase ^(Accept-EncodXng|X-cept-Encoding|X{15}|~{15}|-{15})$ ^((gzip|deflate)s,?s(gzip|deflate)?|X{4,13}|~{4,13}|-{4,13})$ HAVE_Accept-Encoding
Forcing the request header to support compression is straightforward:
RequestHeader append Accept-Encoding "gzip,deflate" env=HAVE_Accept-Encoding
Compressing HTML, TXT, CSS, JavaScript, JSON, XML, HTC:
<IfModule filter_module> FilterDeclare COMPRESS ... FilterProtocol COMPRESS DEFLATE change=yes;byteranges=no </IfModule>
For legacy versions of Apache prior to version 2.1:
<IfModule !mod_filter.c> AddOutputFilterByType DEFLATE text/html text/plain text/css application/json AddOutputFilterByType DEFLATE text/javascript application/javascript application/x-javascript AddOutputFilterByType DEFLATE text/xml application/xml text/x-component AddOutputFilterByType DEFLATE application/xhtml+xml application/rss+xml application/atom+xml AddOutputFilterByType DEFLATE image/svg+xml application/vnd.ms-fontobject application/x-font-ttf font/opentype </IfModule>
One thing to note is that images and PDF files need not be gzipped because they are already compressed by default. To gzip them will waste CPU usage and even increase the file sizes.
An article about gzipping on Yahoo! Network by Marcel Duran talks about the recent research and server-side approach:
http://developer.yahoo.com/blogs/ydn/posts/2010/12/pushing-beyond-gzipping/
Target browsers: cross-browser
ETags stands for Entity tags. An entity is a component like a CSS or JavaScript file, an image, and so on. What an entity tag does is to identify a specific version of a component. You can find more details at Yahoo! Developer Network, High Performance Web Sites: Rule 13 Configure ETags: (http://developer.yahoo.com/blogs/ydn/posts/2007/07/high_performanc_11/).
If you have multiple servers hosting your website, for example, on a content delivery network, ETag's validation mechanism may cause extra re-fetching. There is little advantage in the validation model, so the best practice is to just remove the ETag.
Add the following code:
<IfModule mod_headers.c> Header unset Etag </IfModule> FileETag None
Upload the .htaccess
file to the folder to which you want the rules to apply.
First, we unset ETag for those files that are currently configured:
<IfModule mod_headers.c> Header unset Etag </IfModule>
Second, we use FileTag None
to make sure files have ETags removed:
FileETag None
The following section provides some more information about ETags for your reference.
If you are running an IIS server, to resolve the problem, you must synchronize the ETag values on all the Web servers that are running IIS 5.0 in the Web farm. To do this, use the Mdutil.exe
tool to retrieve the ETag value from one of the Web servers. Then, set the same ETag value on all the other Web servers.
More detailed instructions can be found in the following Microsoft Support article:
Steve Souders has explained configuring rules in his High Performance Web Sites series:
High Performance Web Sites: Rule 13 — Configure ETags:
http://developer.yahoo.com/blogs/ydn/posts/2007/07/high_performanc_11/
David Walsh's blog website contains a post by Eric Wendelin — Improve Your YSlow Grade Using .htaccess and this also mentions the issues addressed in this recipe:
Entity tag removal is also included in the Mobile Boilerplate:
https://github.com/h5bp/mobile-boilerplate/blob/master/.htaccess#L211-L218