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:

Deque FireEyes accessibility testing plugin

I’ve done a lot of accessibility testing and development work over my career. One of the many free tools that I use in that role is FireEyes. Deque also has some commercial packages for developer use.

FireEyes adds a new tab on the Firebug tab bar and adds the ability to analyze a web site for WCAG 2.0 Level A and AA and Section 508 accessibility violations. The Stand-Alone version of FireEyes is a browser plugin to the FireFox browser. It requires that the FireBug plugin already be installed

Requirements:

  • Firefox 31-41

    As of 2015aug21, the current version of the extension is NOT signed and will not execute on later versions. [See my later post on this topic]

  • FireBug 2.x – Do NOT install Firebug v3 alpha as the tab will not show.

NOTE: should be on Firebug tab labeled “Worldspace Fireyes”, but does not seem to be available in Firebug3.

NOTE: if you try to download in MSIE, you must rename the .zip to .xpi, and then open with Firefox.

REFERENCES:

Apache Commons-Email java implementation steps

Many java developers are familiar with the venerable javax.mail.* packages and make use of them in their applications.

While it works well, it can often be cumbersome to work with and difficult to implement new features. Apache Commons-Email, now at version 1.4 (May 2015), provides a simpler interface to send emails with HTML format and attachments.

NOTE: The below examples assume that you are using an SMTP server that verifies the sender. You may need to modify the examples for your specific configuration. Additionally, I’ve left out the try/catch blocks for “Exceptions” that you will have to add.

Using javax.mail.* to send an text formatted message:

final String body = "Example email body";
final String emailFrom = "From User ";
final String emailTo = "To User
";
/* NOTE: 'session' and 'conn' are outside of the scope of this example but generally contain host and authentication information */
javax.mail.Session session = getSession(conn);
final javax.mail.Message message = new javax.mail.internet.MimeMessage(session);
message.setFrom(new javax.mail.internet.InternetAddress(emailFrom));
message.setRecipients(javax.mail.Message.RecipientType.TO, javax.mail.internet.InternetAddress.parse(emailTo));
message.setSubject(subj);
message.setText(body);
javax.mail.Transport.send(message);

Using commons-email for HTML email.

final String body = "Example email body";
final String emailFromAddr = "[email protected]";
final String emailFromName = "User From";
final String emailToAddr = "[email protected]";
final String emailToName = "User To";
final String username = "myusername";
final String password = "mypassword";

final org.apache.commons.mail.HtmlEmail email = new org.apache.commons.mail.HtmlEmail();
email.setHostName("localhost");
email.setSmtpPort(25);
email.setAuthentication(username, password);
email.setAuthenticator(new org.apache.commons.mail.DefaultAuthenticator(username, password));
//email.setSSLOnConnect(true);
final String charset = "UTF-8";
email.setCharset(charset);
email.setFrom(emailFromAddr,emailFromName);
email.setSubject(subj);

email.addTo(emailToAddr, emailToName);
//email.setDebug(true);

// set the alternative message
email.setTextMsg("Your email client does not support HTML messages.");

// set the html message
final StringBuilder sb = new StringBuilder();
sb.append("");
sb.append(body);
sb.append("");
email.setHtmlMsg(sb.toString());
email.send();

Using commons-email with an inline attachment:

final org.apache.commons.mail.HtmlEmail email = new org.apache.commons.mail.HtmlEmail();
/* (insert code from example above above) */
String cid = null;
try{
final URL url = new URL("http://www.example.com/logo.gif");
final String img = email.embed(url, "Logo");
cid = "\"\"";
}
catch(final MalformedURLException ex){
// eat it!
}
// set the html message
final StringBuilder sb = new StringBuilder();
sb.append("");
if(cid!=null){ sb.append(cid); }
sb.append(body);
sb.append("");
email.setHtmlMsg(sb.toString());
email.send();

Code changes to use the library should not take very long as Commons-Email builds on top of javax.mail.*. In most cases, For Maven projects, you can remove the javax.mail references and simply add the new commons-email one to your pom.xml:


<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-email</artifactId>
<version>1.4</version>
</dependency>

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:

HTML4 script defer

This HTML4 attribute was intended to defer/delay execution of specific javascript code until after the page is rendered. In theory, this makes the website “appear” faster as the functions relevant to the User-Interface can be executed before other “background” processes that would otherwise block the screen from displaying.


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

NOTE: Do not use defer for external scripts that might depend on each other if you need to support MSIE9 and earlier.

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:

Adding meta “viewport” for WordPress

Google recently changed their search algoritms to better recognize and weight “Mobile” support. This term is loosely defined in general, but to get your Google search “juice” you simply need to add a “viewport” meta tag. Unfortunately, unless you have the knowledge and want to edit your WordPress theme manually, there’s not an obvious way to add this.

Adding the “Definitely Allow Mobile Zooming” plugin makes this painless in WordPress without any additional configuration.

HTML code required (in <head>):

<meta name="viewport" content="width=device-width" />

PHP required (for manual addition):

<?php
function set_viewport() {
?>
<meta name="viewport" content="width=device-width" />
<?php
}
add_action('wp_head', 'set_viewport');
?>

REFERENCES:

Load Testing web application with Selenium and TestNG

I’ve used Selenium for while to do verification tests of web applications, recently I discovered a very simple way to use it with TestNG and Maven to do some performance testing. TestNG allows for the use of annotations to allow multi-threading and iterations.

pom.xml:

<dependencies>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>6.8.7</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>2.44.0</version>
<scope>test</scope>
</dependency>
<dependencies>

And as for a simple test to get started with… scripting of steps is available online or could be in a future blog post.

/*
* COPYRIGHT. none
*/
package com.example.selenium;

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebDriverException;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testng.Assert;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
/**
* Simple test example for Selenium
*/
public class SeleniumTest {

private static final Logger LOGGER = LoggerFactory.getLogger(SeleniumTest.class);
/**
* TODO Un-comment or change if needed to set your local path!
*/
@BeforeClass
public void oneTimeSetUp() {
System.out.println(“————————————– init —————————————-“);
//System.setProperty(“webdriver.firefox.bin”,”C:\\path\\to\\firefox.exe”);
}
/**
* NOTE: uses TestNG – behaves differently than JUnit
*/
@Test(invocationCount = 1, threadPoolSize = 5)
public void testLoadApp() {

final String fn = “testLoadApp”;
final String baseUrl = “http://www.giantgeek.com/index.php”;
LOGGER.debug(“[START] Thread Id: {} is started!”, Thread.currentThread().getId());

WebDriver driver = null;
final long start = System.currentTimeMillis();
try{
driver = (WebDriver)new FirefoxDriver();
driver.get(baseUrl);

final String actual = driver.getTitle();
LOGGER.debug(“Page Title is {}”, actual);
final String expected = “GIANTGEEK.COM”;
Assert.assertEquals(actual,expected);
//perform whatever actions, like login, submit form or navigation


}catch(final WebDriverException ex){
LOGGER.warn(fn+":WebDriverException:{}",ex);
}catch(final Exception ex){
LOGGER.warn(fn+":Exception:{}",ex);
}
finally {
final long elapsed = System.currentTimeMillis() - start;
LOGGER.debug("[END] Thread Id: {}, elapsed={}", Thread.currentThread().getId(),elapsed);
if(driver != null){
driver.quit();
}
}
}
}

WARNING: Selenium Tests MAY fail if the browser used for testing is updated in the Operating System. Updating the pom.xml to a newer release usually helps!

REFERENCES:

“msapplication-config” and browserconfig.xml

Windows-8/MSIE-11 introduced Tiles, as such server administrators may have started seeing HTTP 404 errors in their server logs as it attempts to look for a “browserconfig.xml” file at the root of a website domain. If you are inclined to use this file, you should definitely look into the documentation for how to best make use of it. Others may just wish to prevent the error from making “noise” in their log files.

To remove the error, add the following to your pages; alternately you COULD define the URL of your file as the ‘content’ attribute:

<meta name="msapplication-config" content="none" />

You can alternately place an empty /browserconfig.xml on your web server for each domain.

An common example of how to use this file is below:

<?xml version="1.0" encoding="utf-8"?>
<browserconfig>
<msapplication>
<tile>
<square70x70logo src="/mstile-70x70.png"/>
<square150x150logo src="/mstile-150x150.png"/>
<wide310x150logo src="/mstile-310x150.png"/>
<square310x310logo src="/mstile-310x310.png"/>
<TileColor>#8bc53f</TileColor>
<TileImage src="/mstile-150x150.png" />
</tile>
</msapplication>
</browserconfig>

REFERENCES: