In the previous post, I had mentioned that I wanted to build a blog engine that is green on Lighthouse. It implies, the scores of Performance, SEO, Accessibility, and Best practices are above 80. This post resonates that idea and we will get to every bit in detail.
Link to this sectionLighthouse: Performance
That led me to the understanding that, there could be unwanted addons that I might have added. Few plugins that I wanted to use on the page but not required as part of vendor.js.
This was a huge efforts in itself and I compiled them as a separate post in here.
Link to this sectionLighthouse: Best practices
When I was rendering pages there was one common suggestion from Lighthouse to optimise the images that I used on a post. It also gave insights on how much of bytes could be saved if I had done a better compression or loaded responsive images.
Link to this sectionGenerating images that are responsive
For mobile devices or devices that have widths smaller than that of a regular desktop, images of the blog needn't download large images. Especially, this is a collection of blogs that show up images captured on my DSLR. The average size of each JPEG file is in the order of 10 MB. In order to make sure, that the images that the post displays is not too huge, I had to make sure to:
- Convert JPEGs to WebPs so that modern browsers use webp that has higher compression order.
- Compress with quality that is not easily identifiable by the naked eye.
srcsetto use different images based on screen resolution.
- Cached on the server using Cloudflare with a higher cache-expires header.
Link to this sectionConvert JPEGs to WEBPs
There are many tools for this conversion. The reason for using webp is size. webp has proven compression strategies over jpegs and there are an average 30% reduction in file size. In order to convert a set of JPEGs to WEBPs, I use the same "Sharp" library and run a script in node. This converts all the non-converted JPEGs to WEBPs with a quality of 60.
Link to this sectionCompression and multiple image sizes
There are many good tools for this purpose in node, php, rails, and what not. Since, the blog engine was totally built ground up from Ember, I chose node for this purpose as it is easy to hook onto any of the EmberCLI's hooks. I use a library called "Sharp". Perhaps, an ember addon called
ember-responsive-image gets this job done where it converts a list of files in a specific path to a different path with multiple image sizes. This solves 2 and 3 for me. The next step to this process is to use
ember-responsive-lazy-image which loads images, while showing a low quality image placeholder until the image loads.
Link to this sectionCaching on the server
I signed up for Cloudflare which gives free CDN and caching in front of my assets. This makes fetching of assets really fast and almost instantaneous.
Link to this sectionLighthouse: Accessibility
Link to this sectionMaking a11y part of dev cycle
Now that most of content was ready, it was time to improve on the accessibility aspect of the blog engine. Ember's addon ecosystem has got me covered with many addons.
Link to this sectionStep 1: Installing ember-a11y-testing
To simply install ember-a11y-testing, I did the following
ember install ember-a11y-testing
This helps me in catching accessibilty issues upfront during a dev build. And fixing them were so easy!
Link to this sectionStep 2: Disable application wrapper
As per the ember guides to enabling accessible web apps, I had to disable application wrapper. So here's how I did it
ember feature:disable application-template-wrapper
Link to this sectionStep 3: Linting markdown files
Oh yes! This was a very quick way for me to find out if I had made mistakes while writing content in my editor itself. I use VSCode for coding and added the markdownlint extension to capture for header rules mismatch. Though this is a minor addition, this made life easier for me to worry one less thing about my test case failure reporting that there was an error.
Link to this sectionLighthouse: SEO
For any public content to be searchable on the web by search engines, it is important that our content contains the right set of meta tags and the values for each of them. As this blog post was built with ember, ember's ecosystem got me covered for taking care of this.
So the idea behind SEO was to generate a nice snippet around the content whose URL was shared on social media platforms like Twitter, Facebook, etc.
There are many tools in the ember ecosystem that does the job of adding the SEO tags dynamically. I used
ember-cli-meta-tags which had the power of setting the head tags at the route level. So any model's name could be set as the
<title> tag's textnode. It is easy to install as well:
ember install ember-cli-meta-tags
Link to this sectionResults
Since the blog is built using Ember,
- The vendor size of production build with gzip, minification and fingerprinting is of the order of 246.95 KB gzipped.
NoteThis number might be quite high considering static assets. But, if you are interested, you can read more about optimising performance for Ember apps from this blog post.
- The app size of production build is of the order of 6.65 KB gzipped
- The total app CSS is of the order of 1.91 KB gzipped.
NoteSince I did not use external addons that use css, vendor.css was unnecessary. So this was also removed from index.html so that would save one network request.
The following are the Lighthouse metrics screenshot of the index page taken on May 30, 2020. The left holds the mobile metrics while the right holds the desktop metrics.
This was about how I got started. Apparently, over time, I had changed some parts of the blog engine to adopt more exciting strategies. You can read about it here.