Removing Moment.js locales from your Angular app JS bundles

Sébastien Dubois / July 12, 2020

4 min read

Light as a feather

In this article I’ll go over the steps that you need to take to remove unused Moment.js locales from your application’s JavaScript bundles and make it light as a feather (sort of).

What’s the matter with MomentJS?

Moment.js is a very popular & powerful library. It supports formatting and localization of dates/times, allowing to easily display dates / times appropriately for users all around the world.

Unfortunately, it hasn’t followed the trend of modern libraries taking advantage from ES modules (ESM) to provide better modularity. As soon as you import something from “moment” in your code, your JS bundles automatically include all the locales supported by Moment.js. In most cases, this is useless as applications generally only support a handful of locales.

Moment bundle problem

Each Moment.js locale file “only” weights a few KB, but if you add them all together, then it starts to hurt pretty badly; especially for small to medium applications.

Note that the above visualization has been generated by webpack-bundle-analyzer, a super useful tool that I’ve introduced in my previous article: “Analyzing your Angular app JS bundles”.

On the other hand, libraries such as RxJS, Lodash and many more, support importing specific functions/operations only when required, which drastically reduces the bundle size; limiting it to the strict necessary.

This has been a known problem for a while with Moment.js, but there’s hope; as some point this will probably be improved. For now though, we must implement a solution as this is really bad for user experience, performance… and the planet ;-)

Easiest solution for new projects

Fresh projects are probably better off using a library such as date-fns.

date-fns supports importing specific functions separately, which means that it doesn’t needlessly add weight to your JavaScript bundles. This might be explained by the fact that date-fns is a functional library and not an object-oriented one like Moment.js.

date-fns is also very powerful. I can’t compare it in detail with Moment.js, but I believe that both are roughly equivalent. If you’re looking for a comparison of both, then you can check out the following article.

By the way, if you’re looking for Angular support, then know that there’s an equivalent of ngx-moment for date-fns called ngx-date-fns.

Custom Webpack configuration to the rescue

In a recent article, I’ve explained how you can easily customize the Webpack configuration of your Angular applications.

Well the good news is that we can quickly fix the Moment.js bundling issue by customizing the Webpack configuration. What you need to do is to exclude all Moment.js locales by default and manually import those that you need.

Here’s how you can exclude Moment.js locales:

This solution uses the Ignore plugin of Webpack (a core plugin) to ignore Moment.js locale files.

Once this is added to your project, no Moment.js locale will be added to your JS bundles. But of course you’ll want at least one to be included!

To include a locale, you now have to import it explicitly in your application code. You can for instance do it in your “main.ts” file:

With this in place, the JS bundles will only contain what you really need.

Conclusion

In this article, I’ve shown you that, by default, Webpack will include all of the locales that Moment.js supports in your JavaScript bundles.

Given how much weight it adds to the JS bundles, it is important to be aware of this issue and even more important to make sure to avoid it. Fortunately, as I’ve shown above, the fix is really easy to implement once you know how to customize the Webpack build of your Angular application.

Hopefully, this will help you improve your application and make it load fast for end users.

That’s it for today!

PS: check out my Dev Concepts books, join the Software Crafters community, the Personal Knowledge Management community, and come say hi on Twitter!
Discuss on TwitterEdit on GitHub