Now serving over http/2

http/2 is well and truly here, and is even partially supported by Internet Explorer 11. Check out the can I use page for http/2. It’s time to stop bundling your JavaScript and Stylesheets into single files without consideration.

Web server implementation for http/2 is also good, with NGINX having supported it from it’s core install for a few years now.

A big http/2 advantage is that you will not run into http 1.1’s limits on the maximum number of parallel connections to a single domain. These vary between browser with Chrome by default supporting 6 connections (it’s worth noting that each browser install can be manually configured to change this number, although I doubt many people do).

The http 1.1 way

Let’s have a think about what happens when we request an imaginary webpage – – over http 1.1.

Looking at a browser that supports a maximum of 6 connections at a time, imagine our test-page.html contains references to 9 external assets, referenced in the header, all hosted on the same domain.


What is going to happen here? Well, assuming that our cache is empty, the first 6 referenced files will be downloaded first. Anything after the first 6 will be queued until one of the 6 download slots frees up. This will happen when a download completes.

A simplified analogy would be you’re queuing at a checkout, and there are 6 tills staffed by 6 operators. A maximum of 6 people can be served at the same time.

This also happens for Ajax requests to the same domain, which must also form an orderly queue, with a maximum of 6 going over the wire at the same time.

There were a few workarounds for this in the http 1.1 world. One was to combine your assets into bundles. So in our above example, our 3 stylesheets become one single stylesheet, and our 3 JavaScript files would become a single .js file. This reduces the number of request slots needed by 4.

Another way would be to serve your assets from different domains in order to bypass the 6 connections per domain limit. For example, having your images served from and your stylesheets from

Both of these techniques worked well under http 1.1, but had their downsides.

Downside 1 – Serving styles and JavaScript for entire areas of a website that a client may never access

Imagine I have a whole section in my web application that is only for users with admin access. If I’m bundling all application styles and scripts into two respective files, I’m burdening the clients that will never access the admin tools of my application with the code for my admin tool. Their experience of my website would improve if I served them a smaller set of assets that did not include the code needed to run the admin tool that they will never access.

Downside 2 – Maintaining web infrastructure for serving from multiple subdomains

Setting up subdomains requires webserver and DNS configuration. I also then need to work out how I’m going to get the web application’s static assets onto their relevant subdomains. It’s a lot of effort.

The http/2 way

With http/2, you don’t need to bundle anymore, and you can instead split and serve your web app using multiple files without worrying about blocking one of those limited download slots. This is largely because of the improvements in the protocol transport, which have resulted in the recommended minimum limit for browsers implementing http/2 being much greater, at 100 concurrent connections.

Splitting your bundles more logically, instead of bundling into one will result in more, smaller bundles being sent to the client. For example you could have a bundle that contains the JavaScript for the admin pages of a web app, and it’ll only get served to the client should they land on an admin page.

If someone visits your web app and only lands on the homepage, you don’t need to serve them with the code needed to run the admin pages of your web app.

Enabling http/2 on NGINX

Setting up http/2 on NGINX is trivial, with the only change needed being the inclusion of the characters “h2” into the listen definition for your site:

server {
  listen 443 ssl http2;

All you then need to do is restart NGINX, and you’re good to go. You can test this out by taking a peek at the network tab in the developer tools of your preferred browser. Note the “h2” in the Protocol column:

The gains

This is a WordPress blog, and whilst I’ve taken steps to improve it’s performance, I have struggled to get the raw number of assets needed by the site down. After enabling http/2, I got an immediate and significant performance score improvement from Google Lighthouse:

I’ll be migrating this blog to a headless CMS soon which will give me much more control and will hopefully give me a nice score of 100! Watch this space.


  • http/2 is only supported over SSL
  • AWS s3 does not support http/2. You will need to put Cloudfront in front of it in order to get http/2 support
  • Google Cloud CDN supports http/2 out of the box, without any additional services
AngularJs, Technical

Performance Tuning AngularJS Apps

For existing AngularJs apps, there are a few things that you can do in order to try and improve performance.

Destroy no longer needed javascript plugin elements

This should help prevent your Angular App from running into memory problems in the browser. There are basically two approaches to this.

In directives that wrap some sort of plugin (e.g. Slick Slider), you need to listen out for the “$destroy” event and call that particular plugin’s cleanup methods. In the case of Slick Slider, it’s the unslick() method, but it could simply be a call to jQuery’s remove() method, or you could just set the value of the html element to an empty string:

$scope.$on('$destroy', function() {

 // Call the plugin's own api

 // or call jQuery's remove function

 // or, if you aren't using jQuery


Unbind any watches when the current scope is destroyed

When you create a watch on a scoped variable, or on an event in angular, the $watch function returns a function that when called, will remove the watch. Call this returned function when your scope is destroyed as it is no longer needed:

var unbindCompanyIdWatch = $scope.$watch('companyId',() => {
 // Do Something...

$scope.$on('$destroy', function() {

Use One-Time Binding where possible

The less binding going on, the less watchers there are.

If you render values in your dom using angular that you know are only going to be set once and will never change during the lifecycle of the page, it is a candidate for using one-time binding. The One-Time binding syntax is basically two colons – “::”, and can be used a few ways in your html templates:

<!-- Basic One-Time Binding -->

<!-- Within ng-repeat -->
 <li ng-repeat="item in ::items">

<!-- Within ng-show -->
<p ng-show="::showContent">
 Some Content

<!-- Within ng-if -->
<p ng-if="::showContent">
 Some Content


Use “track by” when using ng-repeat where possible

By specifying a property for angular to track an item within a collection by, you will prevent angular from rebuilding entire chunks of the dom unnecessarily. This will give you a performance boost which will be noticeable when dealing with large collections:

 <li ng-repeat="item in items track by item.itemId">{{}} </li>

Ben Nadel has an excellent post on track by that you should checkout.

Of course, you shouldn’t need to tie this up with some one-way binding, as track by would be pointless with a collection that does not need to change.

Cancel no longer required Http requests

If some action happens that means that data that is loading is no longer needed (e.g. a navigation change), you should cancel the no longer required http requests. Most browsers limit the number of concurrent requests to a single domain. So, if your requests are no longer required, cancel them and free up those request slots.

You can do this by simply resolving the promise. Your requirements of when this cancellation needs to happen will be different for every app, so I would recommend that you write a httpRequestManagerService, and marshal any http requests through it that you deem necessary. You can then resolve your promises based on some event – e.g. a navigation change event. Ben Nadel has a good post on cancelling angular requests.

Interchange ng-if and ng-show where appropriate

On the surface, ng-show and ng-if produce the same result. However, under the hood, they behave slightly differently.

ng-show still renders your html no matter what. If it does not need to be shown, the html element with the ng-show directive will simply be marked with a display:none css style.

ng-if will completely remove the html and all children that contain the directive.

There is obviously a cost in completely removing and adding entire chunks of html, however if you are dealing with a lot of html, or if your html within your ng-if contains a lot of angular expressions, I have found it to be more performant than ng-show.

My advice is to evaluate both in each case before making a decision.

Please feel free to throw in any more performance tips in the comments

Entity Framework, Technical

Running SQL commands with EF Code First

Before ORMs we used to write SQL code.

Yes – real, “bare metal” SQL. We used it for our CRUD operations, and to perform other larger data manipulation tasks. The database server should be the quickest way to find, remove and join data – provided you know what you are doing.

Then we started using ORMs and stopped writing SQL. The advantages of this are that we should have reduced our development time, needed fewer developers with a good knowledge of SQL programming, and didn’t have to write lengthy and repetitive SQL statements (anyone who has worked on or built a data warehouse will fully agree).

But with this, we sacrificed control over what SQL was run against our database server, leaving it to the ORM to decide what to run.

Looking specifically at Entity Framework’s code first, lets take a look at how you can run into problems with a delete.

So here’s the scenario. I have a task that pulls in data from an external source every hour and needs to be “mirrored” into a table in my application’s database.  Let’s call the table BatchImportData.

As I do not own the external data and have absolutely no control over it and need to mirror the data into my application’s database, I need to do the following to get the task accomplished:

  • Delete all of the data in the BatchImportData table
  • Grab the data from the external resource
  • Insert all of the grabbed data into BatchImportData

Using EF code first, I would normally expect to delete all records from the BatchImportData table with the following code:

foreach (var batchImportDataItem in context.BatchImportData)

This will work, but it will be slow to execute. At the very least, EF will run a delete statement for every single record that exists in BatchImportData.

If we were writing bare metal SQL, we would write either a single delete statement, or a single truncate statement:

DELETE FROM BatchImportData



We can still do this through EF Code First simply by opening up our DbContext a bit more. Currently, our DbContext will look something like this:

public class DbContext : System.Data.Entity.DbContext, IDbContext
    public IDbSet<BatchImportData> BatchImportData { get; set; }

Let’s add a public method in our DbContext that exposes System.Data.Entity.DbContext.Database.ExecuteSqlCommand:

public class DbContext : System.Data.Entity.DbContext, IDbContext
    public int ExecuteSqlCommand(string sql)
        return base.Database.ExecuteSqlCommand(sql);

    public IDbSet<BatchImportData> BatchImportData { get; set; }

This method will take in a SQL statement and will run it against the database.

You can then call the new ExecuteSqlCommand method that you have just added:

   Db.ExecuteSqlCommand("TRUNCATE TABLE BatchImportData");

We now have a much quicker way of removing all records from a table.

Use with caution!

Do not use this if you are going to build up a SQL statement based on user input. You will make yourself susceptible to an injection attack.

This SQL command is merely a string – it is not strongly typed. If we rename our BatchImportData entity and forget to update this SQL command to reflect this change, we will experience a runtime error.

This opens you up to some potential serious data loss mistakes. The classic being a missing where clause.