Wiki Education Dashboard

Google Summer of Code 2020

I was part of Google Summer of Code 2019 with Wikimedia and I was overjoyed when I came to know that I was going to work with the amazing folks (read: the best mentor anyone could get: Sage Ross) at Wiki Education once again as part of Google Summer of Code 2020.

In 2019, my project was something discrete. I could point you to the parts I worked on which weren’t there before and I could go, “Hey, see this feature? I worked on it!”

But it was going to be different this time around, for my project was abstract, something that could only be felt. My proposal was to improve the loading speed of the Dashboard.

The User Experience for people with low-bandwidth internet was not up to the mark. There were lots of resources needlessly being downloaded which was making the website seem slow.

Problem


  1. Redundant resources were being downloaded.
  2. Some of the JavaScript libraries had bloated sizes.
  3. Some heavy resources which are only used by program organizers were downloaded by everyone.

Solution


  1. Extracting the common resources into a separate file and make all others refer it rather than have their own copy.
  2. Migrating to newer, leaner libraries, thereby significantly reducing the bundle size.
  3. Downloading certain resources only when they are needed and not all the time.

Implementation


  1. First we needed a way to measure the bundle size. For this a Webpack Bundle Analyzer was built into Wiki Education Dashboard via #3879
  2. We had lots of varied tooling in the build process. We decided to have everything in Webpack. That was achieved via #4038
  3. Having put all build process within Webpack, it was a bit slow for developing. Hence Parallel Webpack was added in #4054
  4. lodash was migrated to lodash-es in #4059
  5. Upgraded to the latest, leaner @sentry/browser package in #4064
  6. Shared code was optimised in #4079
  7. Unused locale files and methods were removed from Moment in #4083
  8. JavaScript code that was supposed to be loaded on DOMContentReady but that which wasn't, was loaded correctly in #4088
  9. TinyMCE was dynamically loaded only when needed in #4101

Stats


Now let’s talk some numbers. Before this project began, the overall size of the resources tha were being downloaded on an average client’s browser was nearly 4.43 MB every time.

Now, after we have extracted all the shared code into its own file, it comes to 3.03 MB and there’s a further reduction of nearly 900 KB in the form of not loading the rich text editor TinyMCE for users who don't need it.

So the final tally now comes up at near 2.13 MB — more than 50% reduction from the previous resource sizes. On top of it, all the resources were being downloaded every time a new change is deployed — which is quite often. But now with the shared library code being put in a separate file, nearly 1.14 MB of the resources will be only needed the first time. The library code changes relatively rarely, so caching it separately saves another 1.14 MB if you've visited the site before. Altogether, these changes make the page loading experience faster for people with low-bandwidth internet.

Stretch Goal - JavaScript Coverage


As I completed the objectives of my proposal earlier than anticipated, I worked on the stretch goal of generating coverage report for the JavaScript. Coverage reports are extremely useful as they let you know how much of your code is covered by the tests, and identify the code that isn't being tested — which therefore you might break without realizing it.

Generally, the higher the coverage, more robust an application becomes. But there weren’t well-documented ways of getting this JavaScript coverage data from the main type of tests the Dashboard relies on. After much searching and experimenting, I used JSCover, a Java tool to instrument the code and generate the coverage reports.

The initial version of the coverage did not prove to be too useful as it was done on a huge concatenated file. I tinkered around with the Webpack outputted files and managed to breakdown the modules into their own files.

JSCover report for admin_role_spec.rb
JSCover report for admin_role_spec.rb
The result is that we now have an extensive coverage report for each and every individual file, which is great!

The JSCover integration was done via #4131

TL;DR

Checking out the pull request links posted above will let you know about what my project was all about for the Google Summer of Code 2020.

Still TL;DR?

Check out all my contributions!