It’s hard to believe but today marks the halfway point of my GSoC project. I just finished filling out my evaluation form and soon enough it’ll be time for the final review.
But until that happens, we still have a lot of work to do. So let’s get started!
Note: This is my 4th Bi-Weekly blog. You can find the rest of them here
As always, here’s the list of PRs that I made during these past two weeks.
Issue(s) | Description | Pull Request | Status |
---|---|---|---|
- | convert course lists to JSX | #5039 | Merged |
- | remove lodash from bundle | #5040 | Merged |
- | split bundles based on routes | #5050 | Merged |
- | remove moment recur as a dependency | #5053 | Merged |
#2319 | migrate to date-fns | #5065 | Merged |
- | add Instructions for HMR | #5038 | Merged |
- | fix eslint config | #5052 | Merged |
- | don’t escape dashboard title | #5060 | Merged |
And now, let’s go into a bit more detail.
This is mostly the continuation of my work mentioned in the last blog. I had already converted all campaign lists to React components and I have done the same for course lists. There are still some server-rendered lists remaining - about 4 in total if I’m not mistaken. But they are a bit more complicated and will require some more work.
Having only written React for so long, I was quite bored. So I decided that I would tackle the remaining server-rendered lists sometime in the future. I still expect to have a lot of time before the end of GSoC so hopefully, I can get this over with.
All in all, I converted 3 routes to React components. I also worked on getting the search bar on the explore page to work client side so that the initial page load is faster.
lodash
is a JavaScript library that provides functions that are used to manipulate arrays, objects, and other JavaScript types. Since Javascript has a rather limited standard library, lodash fills the gap.
lodash
is however also famous for its bundle size coming in at around 70KB
. Even when GZIPed, it still comes out at around 25KB
.
For us, this problem was multiplied by the fact that we were also using lodash-es
which provides ES6 exports and supports tree shaking.
Here’s the output from the Webpack Bundle Analyzer Plugin
Not only is lodash one of the largest packages in the bundle, but it’s also included twice - once as lodash
and once as lodash-es
.
When I looked into it, I found that the culprit was just this single line in setOtherEditedArticles.js
import { includes } from 'lodash'
Just this one line was causing the entire package to be included in the bundle. Once I removed it, the bundle size decreased from 1.47MB
to 1.42MB
.
That might not sound like a lot but it’s almost a 3.5% decrease in bundle size. On the web, every byte counts.
moment
is a JavaScript library that provides functions that are used to manipulate dates. Unfortunately, just like with lodash
, it is also a large package. It comes in at around 300KB
(and 72KB
when GZIPed)
This is so bad in fact that we were already using a Webpack Plugin to remove unused locales from the bundle. But even then, as you saw from the graph above, moment was one of the largest packages in the bundle.
And this is not to even mention the fact that we have another date library in our bundle - date-fns. We didn’t use it directly but it was a dependency of chartkick
The first step to moving away from moment
was to remove the moment-recur
package from the bundle.
Fortunately, that was easier than I expected since we weren’t using the capabilities of moment-recur
in the first place.
Once that was done, replacing moment was relatively straightforward. I just had to replace the moment function calls with the date-fns equivalent. The problem was that since moment provided a wrapper around the native date object, finding where this wrapper was being passed and used was a bit of a pain. Unlike moment, date-fns
operated on the native date object.
That being said, I think I have been able to do this correctly. There were some issues surrounding timezone since the native Date object only operates in local time, but I think I’ve been able to get away with it.
The bundle size has decreased from 1.42MB
to 1.37MB
and that brings the total size reduction to just under 7% from the original 1.47MB
Before this, we had just one bundle for all the routes. What this means is that even if the user is on the explore page, they have to download the code for every other route.
With dynamic imports, lazy loading, and Suspense, I was able to easily split the code for the routes into separate bundles. This is a lot more efficient than downloading the entire bundle on every page visit.
This doesn’t affect the overall bundle size but it should help with the initial page load.
For the first time, I’m feeling as if I’ve done almost everything major that I wanted to do.
There’s still work to do but most of it is pretty minor compared to everything I’ve done so far. Here’s what I have in mind presently
I’m sure more things will come up but for now, I’m pretty content with the current state of the project. I couldn’t have asked for more at the halfway stage.
And that’s about it. Have a great day!