How we reduced our website build time by 59%

My name is Aikansh, and I am an intern with the Ops Engineering team at Fyle. During my tenure here, I've absolutely loved working with such talented people over the 6+ months I've spent here. I've learned more about Expense Management than I ever thought I would, and I'm grateful for all the knowledge, support, and guidance the team has provided me. :)

What do I do at Fyle? 

During my internship, I've loved working on the usability issues module, which gave me exposure to varied microservices and how they work in sync. 

Our web strategists, content specialists, and web designers help create the desired results together. However, as developers, we need to tie all the pieces together with the right code for the website. We also run multiple tests to ensure that the site is bug-free and stay alert to be the troubleshooters when necessary.

This internship has helped me hone my skills in front end technologies, workflow in a start-up, management among teams, the importance of design docs, and understanding products we build from the users' perspective. Here’s my experience in reducing our website build time by 59%.

Context to the situation 

For our website, we use the versatile webpack as our module bundler and the excellent jekyll as our site generator. In summary, what we do is compile our ES6 code into an ES5 bundle and place it in Jekyll's main /assets directory. During development, we have Jekyll's server watch for changes and reload the page every time it detects a change in our JavaScript code.

The Problem

As is always the case given the speed of development, our web pages, components, and webpack config grew organically, and the speed of the pipeline was an after-thought. 

Often we had to wait 10 whole seconds for our build to apply simple changes like color:black; to color:blue; :/

But there came a tipping point. Eventually, we snapped and decided to get that build time way down.

tl;dr version

We reduced the build time by 59% with some minor tweaks. (As a bonus, my teammates also like me a lot more now!) ;)


The Approach

After being assigned this challenging yet interesting task, I started by measuring our performance. This really helps to find current bottlenecks, and compare progress as we make changes. 

On running npm run dev, our script for getting the development server up running, we had to wait for ~20-25s for webpack and jekyll to do their jobs.

Then, I noted down the basic points against which we could test our output later. We call these functional requirements:

  1. Production build should not be affected; don't sacrifice the quality of application for small performance gains.
  2. npm script commands should remain unaltered.
  3. There should be noticeable differences in the resolving speed of the build & watch process.

Next up was research; following lots of articles, stackoverflow discussions, github issues threads, and official documentations. 

The Solution

Using some of the suggestions and experimenting with multiple configurations to accelerate the webpack and jekyll build performance, I came up with five 3 second changes to reduce the build time by over 59%.

Sounds good? Let’s get started!

  • Enable persistent caching with the webpack cache-loader

The cache-loader allows caching the result of following loaders on disk (default) or in the database. Cache-loaders can be placed in any chain of loaders and cache the results of previous loaders. By default, it stores the cache in the .cache-loader folder in the project root.

  • Replace Uglifyjs with Terser webpack plugin to minify your JavaScript

Attached below is a snippet from npm trends. As we can see, Terser has gained significant popularity in the past one year. This can be directly attributed to its better performance compared to other minification tools.

Uglify vs Terser: A mini-battle royale
  • Use Shopify’s Liquid-C gem to speed up Liquid parsing

Liquid is a secure templating language developed by Shopify. Liquid is designed for end-users to execute logic within template files without imposing any security risk on the hosting server. Jekyll uses Liquid to generate the post content within the final page layout structure and as the primary interface for working with your site and post/page data.

We took advantage of Shopify’s Liquid-C gem which is written in C to speed up this parsing. For this to work, we simply needed to update our Gemfile.

  • Use Jekyll Include Cache plugin

To see how Jekyll _includes affects site build times, I observed the build profile by running jekyll build --profile. Right away, it was visible that some include files are being called hundreds of times, creating a performance bottleneck.

Now was the right time to make use of jekyll-include-cache, a Jekyll plugin created by Ben Balter that will cache the rendering of our Liquid includes.

“If you have a computationally expensive include (such as a sidebar or navigation), Jekyll Include Cache renders the include once, and then reuses the output any time that includes is called with the same arguments, potentially speeding up your site’s build significantly.”

I started by caching the navigation in the header, footer, cookie consent banner, hello bar, and the schedule demo form on our site. The reason; these components were being called on every page and didn’t change that frequently.

  • Enable Jekyll Incremental flag in development

Incremental regeneration helps shorten build times by only generating documents and pages that were updated since the previous build. It does this by keeping track of both file modification times and inter-document dependencies in the .jekyll-metadata file.

This is how our script to run local setup looks like: 

"dev": "webpack --mode development --devtool inline-source-map --watch & jekyll serve --livereload --incremental"

In summary

These are some of the hacks that helped us reduce our build time considerably. But webpack is a complex creature, and optimization is a dark art. I’m sure of having missed many tricks, but do reach out to me and let me know your thoughts! 

By the way, let me show you an actual picture of our website build now ;)


Aikansh Garg

I am a Member of Technical Staff at Fyle. Away from work, I love to run, work out, and play chess!

More of our stories from

Engineering
How we created a Medium-like blurry background effect

Here's how we improved user experience, decreased load time and made Fyle accessible for users without a fast internet.

Read more...
Bye bye WordPress, welcome Webflow.

This blogpost documents our journey as we bid goodbye to WordPress and migrated to Webflow.

Read more...
How we reduced our website build time by 59%

I came up with five 3 second changes to reduce the build time by over 59%. Here's more about my experience.

Read more...
Hello, Web Technologies!

I’m a first-time entrepreneur and I’ll be recording my learnings and experiments over time. I am always eager to interac

Read more...
The Non-Boring Guide to OAuth 2.0

If you’re developing an application that needs access to a user’s Google / Facebook / LinkedIn information, you’ll need

Read more...
Dealing with Nested Objects in your Web Application

A couple of weeks ago, I ran into a peculiar problem that I think might be useful to talk about. It took me a bunch of

Read more...
Eliminate Boilerplate Java code with Lombok

I’ve been writing a lot of boilerplate Java code, lately — getters, setters, hashCode, equals and toString. Actually, I’

Read more...
Hello, Web Technologies! — Part II

This is a follow-up to my first post about technology choices I made while building out our product. I wanted to pen my

Read more...
Sharing Files using S3 Pre-signed URLs

Amazon’s S3 is a reliable, cheap way to store data. We use it to store user-uploaded images and documents as s3 objects

Read more...
JSON Web Token Concepts

There are many technical articles about JSON web tokens (JWT) on the interwebs, but I haven’t found one that explains...

Read more...

All Topics