Earlier last week I set myself out for a little challenge to get my pet project fronthat.com to pagespeed 100. It was really disappointing to see how slow the original version was. After analyzing user behaviour a complete rewrite was done to improve the user experience.

PageSpeed 100 Score

Caution

  • Google’s PageSpeed tool is not an absolute metric on how “fast” your site is. It’s really just a set of guidelines on how to build your application.

Prioritize Visible Content

Server Side Rendering

The initial load time of the application was long. It required users to download 584kb in assets. First meaningful paint on a regular 3G connection took 10.41s. It was even worse on a lower end device which required additional time for the JavaScript to execute. That’s a lot of time just watching a white blank page.

The solution was to use server side rendering to deliver the initial HTML & CSS to the client. JavaScript loads itself up in the background while the application is completely usable. The user can start engaging with the content as soon as the initial 44kb has been transferred and processed by the browser. This yielded a seemingly instant first meaningful paint time for regular 3G connection even though the JavaScript was still being downloaded and executed in the background.

Ember supports server side rendering with ember-fastboot. Initial payload of data is also included in a script tag inside the initial HTML to avoid additional network request when JavaScript kicks in. If your API is according to JSON-API spec then this is a feature provided out of the box by ember-data-fastboot.

There’s also the added benefit of being more friendly to search engine indexing. Ember-cli-head and ember-cli-meta-tags was used to generate dynamic title & meta tags.

Service Workers

Offline first support was added that all the assets are cached locally and network is used as a fallback. On the second visit the load time for browsers that support Service Workers is considerably lower. Users are now able to access the cached content instantly even when the WiFi at the airport is weak since it defaults to offline first and fetches updates from the server when/if necessary.

Marten Schilstra has released a fantastic set of Ember addons to add Service Workers support.

Render-blocking JavaScript and CSS

All the critical CSS was inlined into the HTML to make it the only blocking resource. Originally ember-paper was used for Material Design like look, but I ended up writing all the CSS from scratch to reduce the amount styles required.

Reduce Server Response Time

Deployment to AWS using fastboot-aws with a Redis cache on top solved the problem. Static assets are still being served over a CDN.

Performance Improvements

The original version was serving a huge list which required about a second of render time each time the user navigated. A virtual scroll library smoke-and-mirrors was added to prevent having to show an ugly loading spinner each time a navigation event happened. Some modifications to were required in order to make it FastBoot/NodeJS compatible. It’s not perfect and has quite a few bugs which should be ironed out when 1.0 lands. Chris Thoburn has done a fantastic job. It performs really well even on an old Samsung Galaxy S3 mini.

Future Improvements

Ember Engines and Lazy Loading

There’s a small delay when JavaScript kicks in which freezes the DOM for about ~500 milliseconds. In theory it should be possible to lazy load JavaScript more gracefully. Ember-engines could probably help. There’s no need to rush loading in the JavaScript since the user can already interact with the page.

Web App Manifest

Having the ability to bookmark a web app to the device’s home screen and display a splash screen would provide a more app-like feeling. It’s a pretty straight forward process that I haven’t got around yet.

Update 06.02.2017

It turns out there’s an Ember addon called ember-web-app for adding web app manifest to your project. It also adds Apple specific meta tags out of the box.

After adding the manifest the app scored 91/100 with Lighthouse. PageSpeed 100 Score

Conclusion

I’m very pleased how convenient it was to make these improvements using the EmberJS addon ecosystem. Ember might not be the most popular choice out there, but it’s the right choice for many projects. The future is looking good. Hopefully Safari adds support to Service Workers soon. We’re very close to the era where user doesn’t have to download a native app for majority of the use cases.