Why Moment.js Isn’t Immutable Yet

This post reflects my opinions about immutability in Moment.js. I do not speak for our entire team.

About five months ago now, I joined the maintainers team of Moment.js. I actually didn’t have much OSS experience before joining the Moment team, so jumping into such a massively popular library has been quite the experience. I have learned a ton about JavaScript, dates, and even how standards bodies work. What I have learned the most about though, is what it means to be an OSS maintainer.

The first thing that I will tell you about any OSS maintainer is that we all want to make you, the user, happy. While we’re admittedly getting some benefit from a ‘personal brand’ standpoint, none of us on the Moment team have ever made a single dollar off of the library directly. We do it for the love of code, and for the love of our users.

Sometimes though, we end up in a position where we can’t deliver to our users in the way that we want to. One such example is changing Moment to have an immutable API.
This issue about making Moment an immutable library has been open since 2014, and in fact discussions of immutability of the library date back to 2012. There are hundreds of comments on the issue, and it gets a +1 type comment or thumbs up at least once a week. With the increase in popularity of React.js, the interest in this issue is going steadily up. We have a couple other big issues that also get +1’d a lot, but the interesting thing about immutability is that the people giving feedback on this issue are PASSIONATE about it. This is not a ‘nice to have’ for them. They believe it is an essential feature of the library that is missing.

Now, it is important to know that all of Moment’s maintainers agree that date and time types should be immutable. If we were sitting down and writing a new date and time library today, that is how we would make it. However, changing Moment to be an immutable API has some  very big logistical concerns for us.

In fact, changing Moment from mutable to immutable is almost like making a different library. If this change is done ‘in full’ and not as an add-on, it potentially creates a breaking change for practically every line of code that uses Moment.

But what does that really mean?

Moment.js has been around for five years, which is an eternity in the world of JavaScript libraries, and it isn’t really slowing down in usage. A quick analysis of some stats:

  • 4.5 million NPM downloads a month
  • 15,000 visits a day to Momentjs.com
  • Average of 75 stack overflow questions a month in the last year
  • 40 GitHub Issues for June 2016 (so far)
  • 21 Pull Requests for June 2016 (so far)

These stats are just for Moment.js core. Moment TimeZone and the docs add many more issues and pull requests.

We have no way of knowing how many people are using Moment. We can know the NPM download number, but I would be surprised if that represents more than half of our user base. Other package managers, CDNs, etc are adding many more.

What we do know is that because of those numbers our workload currently looks like this:

Iskren – Moment.js releases, pull request reviews, major code changes
Tim – All Moment TimeZone code and releases
Isaac – GitHub issue management, pull request reviews
Matt – Moment TimeZone GitHub issue management, Stack Overflow questions
Maggie – Documentation maintenance, Stack Overflow questions

All of us do a little bit of every category you see there, but this is generally how everything shakes out. The critical thing to notice though, is that very little of this time is writing actual code for the library – our fantastic community of contributors is really driving that. We’re just making sure it gets delivered to people.

The trick is, between the paying jobs, family, and stuff that just comes up in life, all of us are kept pretty busy.

We’re actually not concerned about the time it would take to write the code for a new major version of Moment that was immutable. If we agreed upon a time frame, a couple of us could probably set aside the rest of life’s concerns for a couple weeks and get this done.

What we are concerned about is having two forks to maintain. From the outside, it’s easy to say “use SemVer, end of life the other fork, and move on”. We have too many users for this. The bottom line is that we can make as many ‘end of life’ and ‘end of support’ announcements about 2.0 as we want, and we can set as many timelines as we please. It won’t change the fact that Moment 2.0 will be in hundreds of thousands of code bases, if not more, for years to come. One need only look to the prevalence of websites still using jQuery 1.* versions to know this is true.

What this means is that we will still be getting GitHub issues, bug reports, Stack Overflow questions and possibly even pull requests on the 2.0 fork for (potentially) years. And unlike jQuery , we don’t have a foundation backing us to help us have the time to answer these.

And as I said in the beginning, we want to make people happy. So we really don’t want to tell everyone ‘too bad, so sad, upgrade to the newest immutable version.’ Because we’re all coders at our day job. And we all know how difficult it can be to get ‘upgrade JavaScript library’ on a development schedule, especially when that library has made a change like moving to immutability, where potentially every line of your code that uses the library could be affected.

In the face of all that, with the mutability vs immutability issue, it all comes down to this one fact:

The mutable library does what people need it to do.

In writing this library, Tim (the author), Iskren (the current lead), and the rest of the community managed to improve millions of code bases. People use it every day. It solves their problems.

An immutable API would be better. But would it be so much better that we should tell all of the users we have out in the world that we can’t support their (working) code as it is today?

We haven’t ruled out immutability. Maybe it is worth it. It will remain in discussion, along with work-arounds like making this plugin an official plugin that ships with the library, which is frankly a more likely route. But this is why it hasn’t happened yet.

I would ask anybody who is rallying for immutability in Moment this question:

Do you want Moment to be immutable, or is Moment not the library you want?

10 thoughts on “Why Moment.js Isn’t Immutable Yet

  1. I understand your feeling.

    I can’t speak for everyone, but as someone who is asking for immutability, I would of course consider learning and using a different library if the Moment team decides to keep moment as is. Ideal to me is that Moment becomes immutable because date and time functionality is very difficult and Moment is full featured and widely tested.

    That said I’m sure many folks like it as is and there is even more code that depends on it being that way. I don’t think the team should or would ignore these concerns. But there have been some proposals on the board about how to address this while still achieving immutability.

    To answer your question: Is moment not the library that I want? Well not currently, because I would like something that is immutable by default, but it is still the best choice in terms of functionality.

    Like

    1. So, it sounds like from your perspective, the immutable plugin or immutable second API is an acceptable choice, if it keeps you your full feature set. Good to know.

      Like

  2. I understand your feeling.

    I can’t speak for everyone, but as someone who is asking for immutability, I would of course consider learning and using a different library if the Moment team decides to keep moment as is. Ideal to me is that Moment becomes immutable because date and time functionality is very difficult and Moment is full featured and widely tested.

    That said I’m sure many folks like it as is and there is even more code that depends on it being that way. I don’t think the team should or would ignore these concerns. But there have been some proposals on the board about how to address this while still achieving immutability.

    To answer your question: Is moment not the library that I want? Well not currently, because I would like something that is immutable by default, but it is still the best choice in terms of functionality.

    Like

  3. It’s a complex decision, indeed.

    I’m currently using Moment in many closed-source projects and I (and my team) would be willing to invest the time to migrate to a new, immutable version of Moment, because immutability is very important for us.

    However, I completely understand your quandary. And now that you asked the question ‘is Moment not the library you want?’, it made me think that I should look into js-joda (https://github.com/js-joda/js-joda); perhaps that’s the library we’re after.

    Thanks

    Like

    1. A couple of us on the moment team keep any eye on that library. Matt and I are both big NodaTime fans (Matt actually contributes a bunch to NodaTime), so we lust after having the NodaTime types in JavaScript a bit. I give a conference talk on date and time in JavaScript and I always recommend that one as my favorite competing library.

      Like

    2. I, too, see a willingness to invest time to migrate to an immutable API if it happens.

      Surely, the group of users who WANT a mutable API (given a fresh start) must be an extreme minority.

      Like

  4. Nice article and good points.

    As a long-time moment user (4+ years), my problem with the frozen-moment plugin approach are two things:

    1. The need to call .freeze() to get an immutable object. It’s easy to forget to do this.
    2. This: “Frozen moments attempt to play nice with other Moment.js plugins, assuming that the Frozen Moment plugin is loaded last and/or moment.frozen.autowrap() is called after the last Moment plugin has been initialized. That said, we cannot guarantee that every plugin will behave correctly.”

    I think you are blowing the effects of 3.0 immutability out of proportion. Most codebases will probably “almost work” when upgrading to moment 3.0. Avoiding mutation is such a widely adopted good-practice, so a lot of people using Moment 2 are doing it with the “always clone()” pattern. Consider the other way around – going from an immutable to a mutable API – that would be much more problematic. Going from mutability to immutability is benign.

    And besides the relatively low impact of 3.0 immutability: Moment 2 is fine! I personally don’t think it needs much maintenance. I’m also guessing you are, in internal discussions, drawing parallels to how Angular 2 alienated its user base with a complete API overhaul. In my opinion, Moment 3 immutability is nothing like this. Firstly, immutability is widely requested and wanted by the community (as opposed to the Angular 2 surprise). Secondly, compared to the Angular 2 overhaul, Moment immutability is a fairly small API change.

    Lastly, I want to encourage you to speak at the http://nordicjs.com/speakers conference. I think this topic would make an interesting speech and discussion.

    Like

    1. We’ve been talking with Lucas, the author of Frozen Moment, and we think we’re going to be able to resolve concerns related your points. I’ll probably have an update blog post later this week.

      Like

    1. Yes! It’s probably owed a blog post but I’ve admittedly just been at-capacity dealing with TC39 stuff and work stuff and haven’t been giving Moment hardly any love. Isaac Cambron from the original moment team wrote that library and IMO it’s beautiful.

      Like

Leave a comment