Use of lower-case HTML5 DOCTYPE as a network micro-optimization

TLDR; using lowercase in markup improves the compression as the dictionary for the algorithm will be smaller. Most HTML/JS/CSS is case insensitive and can be optimized as lowercase.

micro-optimizations can be fun… or an utter pain.

I’ve been on both sides of this debate at times, at one time had sub-second SLA’s for a web based customer service app that ran out of a UK data-center with users in South America.

This helped build a thorough understanding of how to best use the browser cache, progressive page loading, and optimization of image and network compression.

Webserver extensions like Google mod_pagespeed definitely help automate some of this stuff on the output, but nothing is ever robust as just building the application with performance in mind.

As a java shop (at that time), JSP exposes a lot of config to eliminate white-space in generated output, that often saved up to several K per page. I’m always amazed when I find large companies that still do not utilize those features, as “bandwidth is cheap” for the provider… but not always for the end user.

REFERENCES:

Minify .js files during Maven builds

Minifying files for use on the web is essential to improving performance, to reduce network overhead as well as a slight bump in execution speed.

Long ago I used the YUICompressor plugin for both JS as well as CSS files, unfortunately that project appears to have been abandoned many years ago and no longer functions well for JS files that make use of modern features.

For JS files, I’ve found that most capabilities can be replicated with the following in the pom.xml:

<plugin>
<groupId>com.github.blutorange</groupId>
<artifactId>closure-compiler-maven-plugin</artifactId>
<version>2.21.0</version>
<executions>
<execution>
<id>default-minify-js</id>
<phase>generate-resources</phase>
<configuration>
<!-- not supported (always uses .min) <suffix>-min</suffix> -->
<encoding>UTF-8</encoding>
<baseSourceDir>${basedir}/${webapp-folder}</baseSourceDir>
<baseTargetDir>${webapp.path}/</baseTargetDir>
<sourceDir>js</sourceDir>
<targetDir>js</targetDir>
<skipMerge>true</skipMerge>
<includes>
<include>**/*.js</include>
</includes>
<excludes>
<exclude>**/webjars-requirejs.js</exclude>
<exclude>**/bootstrap*.*</exclude>
<exclude>**/jasmine*.*</exclude>
<exclude>**/*-min.js</exclude>
<exclude>**/*.min.js</exclude>
</excludes>
</configuration>
<goals>
<goal>minify</goal>
</goals>
</execution>
</executions>
</plugin>

NOTE: the only feature I have not yet been able to match is the suffix, as it appears to always use *.min.js (where I used to prefer *-min.js).

An additional advantage of using the plugin is that many common syntax errors will be identified at build time, before they cause user problems… but they will also break your build!

REFERENCES:

Minify .css files during Maven builds

Minifying files for use on the web is essential to improving performance, to reduce network overhead as well as a slight bump in execution speed.

Long ago I used the YUICompressor plugin for both JS as well as CSS files, unfortunately that project appears to have been abandoned many years ago but is still effective for CSS even if it is less useful for modern JS.

NOTE: default extension uses -min, to change it set property ‘maven.yuicompressor.suffix’ to the desired value, such as .min to match GCC used for JS.

For CSS files, you can use following in the pom.xml (JS is also possible if you are not using ES6 features):

<plugin>
<groupId>net.alchim31.maven</groupId>
<artifactId>yuicompressor-maven-plugin</artifactId>
<version>1.5.1</version>
<executions>
<execution>
<id>compressyui-min</id>
<phase>prepare-package</phase>
<goals>
<goal>jslint</goal>
<goal>compress</goal>
</goals>
</execution>
</executions>
<configuration>
<nosuffix>false</nosuffix><!-- false will create -min versions, true does not -->
<warSourceDirectory>${basedir}/${webapp-folder}</warSourceDirectory>
<webappDirectory>${webapp.path}/</webappDirectory>
<jswarn>false</jswarn>
<gzip>false</gzip><!-- create .min.gz files -->
<nocompress>false</nocompress>
<force>true</force>
<excludes>
<exclude>**/*.js</exclude><!-- YUI cannot handle ES6 const let, use closure-compiler instead -->
<exclude>${webjars-output.path}*.*</exclude>
<exclude>**/webjars-requirejs.js</exclude>
<exclude>**/bootstrap*.*</exclude>
<exclude>**/jasmine*.*</exclude>
<exclude>**/*-min.css</exclude>
<exclude>**/*.min.css</exclude>
</excludes>
</configuration>
</plugin>

REFERENCES:

Squid3 Proxy on Ubuntu

Using a personal proxy server can be helpful for a variety of reasons, such as:

  • Performance – network speed and bandwidth
  • Security – filtering and monitoring
  • Debugging – to trace activity

Here are some simple steps to get you started,  obviously you will need to further “harden” security to make it production ready!


sudo apt-get install squid3


cd /etc/squid3/
sudo mv squid.conf squid.orig
sudo vi squid.conf

NOTE: the following configuration works, but will likely need to be adapted for your specific usage.


http_port 3128
visible_hostname proxy.EXAMPLE.com
auth_param digest program /usr/lib/squid3/digest_file_auth -c /etc/squid3/passwords
#auth_param digest program /usr/lib/squid3/digest_pw_auth -c /etc/squid3/passwords
auth_param digest realm proxy
auth_param basic credentialsttl 4 hours
acl authenticated proxy_auth REQUIRED
acl localnet src 10.0.0.0/8 # RFC 1918 possible internal network
acl localnet src 172.16.0.0/12 # RFC 1918 possible internal network
acl localnet src 192.168.0.0/16 # RFC 1918 possible internal network
acl localnet src fc00::/7 # RFC 4193 local private network range
acl localnet src fe80::/10 # RFC 4291 link-local (directly plugged) machines
#acl SSL_ports port 443
#http_access deny to_localhost
#http_access deny CONNECT !SSL_ports
http_access allow localnet
http_access allow localhost
http_access allow authenticated
via on
forwarded_for transparent

Create the users and passwords:

sudo apt-get install apache2-utils (required for htdigest)
sudo htdigest -c /etc/squid3/passwords proxy user1
sudo htdigest /etc/squid3/passwords proxy user2

Open up firewall port (if enabled):

sudo ufw allow 3128

Restart the server and tail the logs:

sudo service squid3 restart
sudo tail -f /var/log/squid3/access.log

OTHER FILE LOCATIONS:

/var/spool/squid3
/etc/squid3

MONITORING with Splunk…

sudo /opt/splunkforwarder/bin/splunk add monitor /var/log/squid3/access.log -index main -sourcetype Squid3
sudo /opt/splunkforwarder/bin/splunk add monitor /var/log/squid3/cache.log -index main -sourcetype Squid3

REFERENCES:

HTML5 Link Prefetching

Link prefetching is used to identify a resource that might be required by the next navigation, and that the user agent SHOULD fetch, such that the user agent can deliver a faster response once the resource is requested in the future.


<link rel="prefetch" href="http://www.example.com/images/sprite.png" />

<link rel="prefetch" href="/images/sprite.png" />

Supported in:

  • MSIE 11+/Edge
  • Firefox 3.5+ (for HTTPS)
  • Chrome
  • Opera

REFERENCES:

HTML5 DNS prefetch

I often get into some fringe areas of micro-optimizations of website performance, DNS prefetching is another one of those topics.

To understand how this can help, you must first understand the underlying concepts that are used within the communications used to build your web page.

The first of these is a “DNS Lookup”, where the domain name (www.example.com) is converted into a numerical address, the IP address of the server that contains the file(s).

In many websites, content is included from other domains for performance or security purposes.

When the domain names are known in advance, this approach can save time on the connection as the lookup can fetched in advance, before it is required on the page to retrieve assets.

This can be particularly useful for users with slow connections, such as those on mobile browsers.


<link rel="dns-prefetch" href="//www.example.com" />

Supported in:

  • MSIE9+ (MSIE10+ as dns-prefetch)/Edge
  • Firefox
  • Chrome
  • Safari
  • Opera

REFERENCES:

Brotli Compression

If you look at HTTP Headers as often as I do, you’ve likely noticed something different in Firefox 44 and Chrome 49. In addition to the usual ‘gzip’, ‘deflate’ and ‘sdhc’ , a new value ‘br’ has started to appear for HTTPS connections.

Request:

Accept-Encoding:br

Response:

Content-Encoding:br

Compared to gzip, Brotli claims to have significantly better (26% smaller) compression density woth comparable decompression speed.

The smaller compressed size allows for better space utilization and faster page loads. We hope that this format will be supported by major browsers in the near future, as the smaller compressed size would give additional benefits to mobile users, such as lower data transfer fees and reduced battery use.

Advantages:

  • Brotli outperforms gzip for typical web assets (e.g. css, html, js) by 17–25 %.
  • Brotli -11 density compared to gzip -9:
  • html (multi-language corpus): 25 % savings
  • js (alexa top 10k): 17 % savings
  • minified js (alexa top 10k): 17 % savings
  • css (alexa top 10k): 20 % savings


NOTE: Brotli is not currently supported Apache HTTPd server (as of 2016feb10), but will likely be added in an upcoming release.

http://mail-archives.apache.org/mod_mbox/httpd-users/201601.mbox/%[email protected]%3E

Until there is native support, you can pre-compress files by following instructions here…
https://lyncd.com/2015/11/brotli-support-apache/

REFERENCES:

Install WireShark on Ubuntu Linux

WireShark is an invaluable tool in recording and reviewing network traffic, it was previously known as Ethereal and is available for a variety of platforms.

Installation can sometimes be hard to remember as use by non-superusers requires additional configuration in Linux.

  1. Add the repository and install:

    sudo add-apt-repository ppa:wireshark-dev/stable

    sudo apt-get update

    sudo apt-get install wireshark

  2. During installation, the following will appear, chose "Yes" for most instances.


    Should non-super users be able to capture packets - Yes / No?

  3. If you need to change the value you selected, you can always re-run the following:


    dpkg-reconfigure wireshark-common

  4. Add the user to the wireshark group so that they can capture traffic:


    add user to group:
    sudo usermod -a -G wireshark username
    id username

  5. If you need additional information, you can always RTFM:


    sudo vi /usr/share/doc/wireshark-common/README.Debian.

REFERENCES:

Install Google mod_pagespeed for Apache HTTP

Website network performance is usually a very complicated process. Over the years, I’ve outlined many development techniques that can be used toward this goal. I’d heard about mod_pagespeed for some time, but never had the opportunity to experiment with it until recently. My first impression is that it is a VERY EASY means to gain performance improvements without reworking your existing website to implement techniques for establishing far-future expires, cache-busting, minification and static file merging.

Out of the box, most common techniques are automatically applied to your assets and a local server cache is created to utilize them.

Default installation is trivial:

  1. Download the latest version for your server architecture:

    wget https://dl-ssl.google.com/dl/linux/direct/mod-pagespeed-stable_current_amd64.deb

    OR

    wget https://dl-ssl.google.com/dl/linux/direct/mod-pagespeed-stable_current_i386.deb

  2. sudo dpkg -i mod-pagespeed-*.deb

  3. sudo apt-get -f install
    (if required)

  4. sudo service apache2 restart

NOTE: Using tools like Firebug will enable you to see an HTTP Header indicating the version being used for your requests.

If you need to modify configuration from the default:

sudo vi /etc/apache2/mods-available/pagespeed.conf

For VirtualDomains, you can selectively enable and disable PageSpeed and many of it’s settings in your appropriate configuration files with:

<IfModule pagespeed_module>
ModPagespeed on
</IfModule>

NOTE: Appending ?ModPagespeed=off to your URL will disable functions for that request.

REFERENCES:

HTML5 script async

The HTML5 “async” attribute simplifies page-load performance improvements and dynamic script loading, it can be useful in modern web browsers.

Simply put, this tag allows for the browser to asynchronously load and execute external javascript files in a parallel vs. serial manner. Unfortunately while most modern browser support it, MSIE versions prior to MSIE10+ are problematic.


<script src="example.js" async="async"></script>

This is particularly useful when using third-party javascript libraries and utilities that have no dependeny relationships with your existing website javascript.

REFERENCES: