All good things must come to an end. And so does my GSoC journey. It’s been a great experience contributing and I’ve learned a lot.
While things had to slow down towards the end(college says Hi!), I’m glad that I was(mostly) able to finish all the work that I had planned.
I’ve already gone into a lot of detail about the work that I’ve done in my previous posts, so at the risk of sounding repetitive, I’ll just go over the major things that I’ve done.
But first, a bit about my project. I assume if you’re reading this, you already know what my project is about, but just in case, here’s a quick summary.
I’ll borrow the following from my proposal:
Wiki Education Dashboard (the Rails app that powers Programs & Events Dashboard) is a complex web app for keeping track of contributions to Wikimedia projects. It’s widely used by the global Wikimedia community for edit-a-thons, classroom wiki writing assignments, and a variety of other initiatives.
This project aims to look for areas of improvement in the javascript side of the dashboard. A major part of this would be replacing older dependencies that are no longer maintained with newer ones, reducing the bundle size, while also making the codebase in line with the rest of the JS ecosystem. This project will also involve rewriting some of the legacy code in a more modern way, making it more approachable to a wider audience of developers and contributors.
To make things easier, I’ll be dividing my work into 3 parts:
The JS tooling ecosystem is incredibly vast. There are a lot of tools that do the same thing but with different syntaxes and different approaches. Finding which tool is the best for a given project is a very difficult task.
Even when you decide what to use, maintaining and updating the tooling can be a pain. Most of the time things just work, but when they don’t, it’s a nightmare to debug.
In a sense, the tooling around the code is more difficult to maintain than the code itself. But good tooling is a must for a good developer experience so that’s what I worked on for the first half of my project.
Webpack is the tool that we use to bundle our code. It’s a very powerful tool, but it’s also very complex. It takes a lot of work to configure it properly and it’s easy to make mistakes, given the huge number of plugins, loaders, and options that it has.
I worked on upgrading Webpack to version 5 from version 4, along with improving the build performance by using several different caching techniques.
The majority of this work was done in #4982
Hot Module Replacement(HMR) is a feature that allows you to see the changes that you make to your code without having to reload the page. It preserves the state of the application and makes the development process a lot faster.
I worked on getting HMR to play nicely with our Rails backend. This was done in #5013
Code coverage is a measure of how much of your code is being tested. It’s an important metric to measure the quality of your tests. While we had coverage reports before, they were hard to parse since they didn’t work on the actual source code but the code bundled by Webpack.
I made source maps work with the coverage reports by switching from JSCover to Istanbul for generating the coverage reports. This was done in #5002
These coverage reports are uploaded automatically to CodeClimate and are publicly viewed here.
Yarn is a package manager for Javascript, just like NPM. Yarn v3 is noticeably faster than v1(which we were using before) and I worked on the upgrade.
This was done in #5022
Bundle Analyzer is a tool that allows you to visualize the size of your bundle. It’s a great tool to identify the parts of your code that are taking up the most space.
I worked on integrating Bundle Analyzer into our build process. This was done in #5040
The bundle size is the size of the Javascript code that we ship to the user. It’s important to keep it as small as possible since it affects the load time of the application.
Javascript is loaded in a blocking(ie, synchronous) manner, so the larger the bundle size, the longer it takes for the user to see anything on the screen.
I’ve worked on a lot of different things to reduce the bundle size, but I’ll limit myself to the ones which took the most effort(and time).
React DnD is a library that allows you to create drag-and-drop interfaces. It’s a lot more involved than other drag-and-drop libraries, but that also means that it’s a lot more powerful.
The upgrade to v16 of React DnD was appealing not only because it fixed some bugs, but because it also substantially reduced the package size.
Unfortunately, the upgrade required a bit more work since the old class-based API no longer existed. This meant that our entire drag-and-drop system had to be rewritten to use Hooks instead.
This was done in #5093
moment.js
is a library that allows you to work with dates and times. While very popular, it’s currently in maintenance mode and is no longer being actively developed. It is also a fairly large library, so I worked on replacing it with a smaller alternative - date-fns
.
This was done in #5065
jQuery probably needs no introduction. Its been indispensable for Javascript developers for a long time. But with modern JavaScript, jQuery’s abstractions are often no longer necessary.
Our application still uses a lot of jQuery but I worked on replacing it with vanilla JavaScript wherever possible. I also ensured that jQuery is loaded only when necessary.
This was an ongoing effort spread across multiple PRs but the most notable one was #5098
The last part of my project was to lay the groundwork for future improvements. What I mean by this is that while these changes haven’t had a direct impact on either the user or developer experience, they will make it easier to make future changes.
React provides 2 ways to model components - classes and functions. Class based components are the ones that we’ve been using so far. Functional components are a lot simpler and are the recommended way of writing components in React.
Many of our dependency upgrades now require us to use functional components - I’ve already mentioned React DnD but React Router v6 also requires us to use functional components.
I’ve converted several class based components to functional ones during my internship. A lot more work needs to be done here, but I’ve added some documentation to make it easier for future contributors to convert the remaining components.
Despite the majority of our application being rendered client-side, we still have a few server-rendered tables. These tables are rendered on the server and then sent to the client as HTML. Then the client-side Javascript takes over and adds interactivity to the table.
We use list.js
to add this interactivity. Replacing the server-rendered tables with React components would allow us to remove list.js
as a dependency and reduce the bundle size.
I worked on converting quite a few of these tables to React components. This was done in #5039 and #5026
As I mentioned earlier, jQuery was a big part of our codebase. During my internship, I’ve worked on removing it wherever possible.
As of writing this, jQuery is only used in a couple of places now - the campaigns route and the survey route. The long-term plan for these is to convert them to React components but doing so will require a lot of work. This is something that I had hoped to do but unfortunately, I didn’t have the time.
While I’ve tried to list everything of importance above, there’s still a lot missing from the list. Here’s a list of all the PRs that I’ve made during my internship.
You can also view my PRs in detail here. A lot of these PRs were made before I officially started my internship but they all helped further my understanding of the codebase.
Then there’s my blog posts where I go into considerable detail about the work that I had done that week.
As I look back on my proposal, I feel quite satisfied with the work that I’ve done. I did skip the rewrite of the survey system(after discussing it with my mentor) but other than that, I was able to contribute to more areas than I had initially anticipated.
Of course, I had a lot of help along the way and I can’t fail to thank my mentors for everything that they did. While Dhruv wasn’t much involved in the latter half of my internship, he was a great help nonetheless - especially when it came to Webpack and the entire tooling process.
And then there’s Sage - I feel like I’ve already mentioned him a million times in these blog posts so I won’t repeat myself but I would once again say that I couldn’t have hoped for a more cool mentor!
And with that, I conclude this series of posts about my GSoC internship. I hope you enjoyed reading this series of blog posts as much as I enjoyed writing them. I had gone into considerable technical details about everything I did in the hope that someone reading it might learn and benefit from it.
And as always, thanks for reading!