The difficulties we are having with updating our Ember projects

I’ll start by saying that Ember has served us well, we have written what we think are a number of decent projects, which make use of shared components that we wrote ourselves and we have reached a point where we can get going with brand new projects quickly with a lot code reuse.

However, we are a relatively small team with quite a lot of code to maintain and improve and updating our Ember projects to use the latest versions of Ember is getting very expensive. We have a six monthly release cycle and during that time we try and update to the latest version of Ember and other packages as best we can. There are often deprecation warning messages in the console and we mark certain deprecations as ones we will target next time or some warnings come from old packages that have stopped being maintained and we then have to decide if we maintain those packages locally (if MIT licensed, etc.) or we use a different package.

Our projects are currently at 3.12, but the upgrade to 3.20 is taking a long time. We have a person constantly working on upgrading all the projects and he has only got through a few of them during the this release cycle. The Octane upgrade seems to have caused us additional problems than we usually have during an upgrade.

Is anyone else having these same issues?

What I would really like to see is a longer LTS cycle and for the LTS to be on a major version rather than a minor version. It would be so good if an Ember 3 got bug fixes for 3 years and security patches for 5 years and any library that worked for Ember 3.0.0 works with all other versions of Ember 3.x.y (with x versions improving functionality and adding new functionality, but without breaking changes, and y being bug fixes). The problem with the Octane release is that libraries are now using native classes which is breaking our code that extends EmberObjects from these libraries, and some older libraries still use EmberObjects so we have a bit of a mess of new and old styles in the code. For me Octane feels like it should have been an Ember 4 release.

Note that we are happy Ember has fast releases and is well maintained and upgraded.

Do you guys see Ember becoming relatively stable soon? If we have to keep putting this much effort into updates we will have to look at other frameworks (although they all might have the same issues).

It sounds like your team is doing a lot of upgrade work that is really optional and not mandatory.

For example, rewriting everything from @ember/component to @glimmer/component would be a huge amount of work which is why there are absolutely no plans to remove @ember/component and you’re not expected to do that. An app can be fully “octane enabled”, meaning you have access to all the new features and all new code will be generated in octane style, without changing any of the existing things to octane style.

To stay on a supported Ember version, the only upgrade activity that’s mandatory is clearing deprecation warning before a major release. And we’ve maintained major-version stability for the past three years! (Ember 3.0 was February 2018, and as yet there is no breaking Ember 4.0).

If you can share some more details about the kinds of work your team is doing, maybe we can figure out how to help alleviate those concerns.

Hi @KroneckerDeIta, thanks for sharing your experience. I’ll start by saying I don’t think you’re alone, and I’m in a similar situation where we have an extremely small team maintaining a lot of code, and are running into some of the same sorts of things. We recently finished upgrading our app to 3.20 and while it the upgrade itself was a challenge (we were at 3.0 not that long ago) it was well worth it. And also that said I think the tooling and community support around upgrading is actually best in class and far easier than in other javascript framework ecosystems. I’ll get to that later though…

Ember release cycle

I’m not core team or anything so I can’t speak with any authority here but I think there are a few ideas in the ember release cycle that might be good to explain a little bit. When you said “For me Octane feels like it should have been Ember 4 release” I think that’s exactly opposite the intention behind the idea of Ember Editions. I don’t recall exactly when/where, maybe EmberConf, but when Tom and Yehuda were introducing the concept of editions they spoke about how there are periods of churn and new features, etc followed by periods of stability and polishing and consolidation. Ember has (for a while, at least since 2.x) taken the stance that a major release should only remove deprecated APIs, not add new features. A major release indicates that the library has undergone a transformation and not only added a bunch of cool new stuff but also shed baggage from preceding versions. A major version is entirely breaking changes in that sense.

The concept of editions (the first of which was Octane) was introduced to signal the other side of the churn/stability cycle, wherein a set of new features is landed (incrementally) and cohesively referred to as an Edition, while the framework starts to deprecate old APIs that have been replaced in anticipation of the next major release. That’s the stage we are in now, working towards the Ember 4.0 release after having landed Octane and steadily working on deprecating old/confusing/load-bearing gross APIs, and also fill API gaps for things that didn’t make it into the Octane edition proper.

So if it feels like there was a lot of churn recently, well, there was. That said there are a lot of things done to reduce churn during these periods for LTS apps. New features are, as a general rule, optional and can be adopted incrementally. We upgrade our app (and subapps and whatnot) at my company but it will take a LONG time for us to convert everything to Octane conventions, and there’s no reason to be in a huge rush. Our stance is “if you touch old code, refactor it” but otherwise we leave it alone. Tackling deprecations is most important but if you use deprecation workflow you can get through those incrementally too, and for the most part all the recent deprecations won’t be breaking (removed) until 4.0, so there’s plenty of time.

Of course there is also the LTS release cycle. I believe it’s 30 weeks between LTS releases. This is quite a long time in the javascript world. I know you mentioned 3 years and 5 years which sounds standard in some development communities but honestly I just don’t see that being possible in javascript. The javascript/web/browser ecosystem moves so quickly that just doesn’t seem possible. Javascript itself looked extremely different 3-5 years ago, and so did all the tooling that any of the major frameworks used.

So when it comes to answering your question “do you see Ember becoming relatively stable soon?” the answer is complicated. Yes, because we are nearing the end of the churn part of the cycle and entering the stability cycle. No because it’s javascript and things will probably always move fast.

Ember vs the greater javascript ecosystem

I want to give a big fat preface here that I’ve never maintained a long-lived React/Vue/etc app personally. I’ve mostly used them for shorter/smaller/academic exercises. That said I have good friends who do both, and I pay attention to the greater js ecosystem as much as I can, so I’m not just talking out of my butt here either… I think no matter where you go the story is going to be the same or far worse.

One of Ember’s core values is “stability without stagnation”, and a couple more are “batteries included” and “convention over configuration”. Between these two general ideas, and the consistency with which they are embodied in the framework and community, I think you have something truly rare in the javascript world. React, for example is a tiny library by itself, and the rest of the ecosystem is (at least in my opinion) a nightmare of different libraries and metaframeworks and tooling. Everyone wants to roll their own router and build system and so on. Maintaining a large project built on that kind of approach means the company is sort of creating its own metaframework. With Ember conventions are strong, community consensus helps keep tooling decisions to a minimum, and so you can expand that idea of framework ownership to everyone. Most Ember apps look the same, familiar, approachable, and conventional, and that makes things much easier to maintain over time.

Making upgrades more bearable

So obviously to some extend upgrades always suck and you just have to do them and there’s no way around it. This is true in literally any code project, manyfold in any javascript framework. But there are some things which you can do to make them much easier.

  • stick with convention, follow the Ember guides and lint rules and so on, follow the “happy path”, try to use good community endorsed patterns
  • be very choosy about what addons and 3rd party libraries you let into your project, addons and 3rd party libs are some of the biggest upgrade headaches in my experience. So many are well worth it but you have to be careful to weigh the long term cost of every addon you adopt
  • stick with LTS upgrades, don’t do big bang upgrades
  • handle the changes and deprecation incrementally, don’t do massive sweeping changes, new features aren’t required, just encouraged so adopt them as you see fit

Parting thoughts

I think partly this is an issue of expectations. To be frank, it might just require a bit of adjustment and acceptance. Upgrades happen, the javascript ecosystem moves fast, and there’s only so much you can do about it. Partly I think you can mitigate the “damage” by sticking with convention, being cautious about 3rd party code, and just having a relaxed attitude about refactoring code. It takes a long time in a big app, and that’s ok.

Also pay attention to the community and always feel free to reach out for help. Ember’s community is one of its strongest points in my opinion and there are so many great devs with similar experiences and lots of ideas and tips to offer.

All that said, it sounds like you’ve done some great work. I’m obviously biased but keep going, stick it out, make some adjustments to your process if you need, and enjoy the ride :grin:

Edits

EDIT: as far as addons go, Ember core team/framework couldn’t (and shouldn’t) make any rules about how third party addon authors maintain their code other than best practices and happy path tooling like ember-try. Unfortunately that means a lot of addons aren’t always going to be documented well or consistent in regards to which versions of Ember they are supposed to work with, though many of the popular ones set a good example in their READMEs and changelogs/release notes. What that really means is you have to be careful when updating your 3rd party stuff. If you have a robust test suite that you feel confident in a tool like greenkeeper or dependabot could be useful as they will open per-dependency PR branches to test with your app.

2 Likes

Thanks for the detailed responses, which have answered my questions. I will send a more detailed response when I get time over the weekend. As you point out it is the third party ember- libraries where I think we have the most difficulty during upgrades. We will diligently read release notes and apply the codemods and things seem to be mostly ok in our code. We also always try and go for the more popular third party ember- libraries and hope that they continue to be maintained, but the problems we find are usually not with those libraries though, but the ember- libraries that are dependencies of those libraries (or even further down the tree). Maybe we need to tackle this in a different way, look at ways of finding what libraries will break up front, and as you mention make use of ember-try.

@ef4 Yeah we were originally going to try and do a full upgrade on all projects (go to native classes, etc.), but after doing it for one of our smaller projects we decided against it for the remaining projects.

As an example of one of the problems we have run into: We were using an older version of ember-power-select we extend in our code, which uses an old version of ember-concurrency, which seems to not work with Ember 3.20 (it looked like an import error, which took a little while to diagnose). So we decided to update to a newer version of ember-power-select. However, ember-power-select now uses native classes, so our extension of the object no longer worked, and the mixins we were using could no longer be used so we had to duplicate code. We have faced many other issues during upgrades over the last few years, but this example shows there must be breaking changes going on.

@dknutsen mentioned being cautious with third party code, and we (my company) needs to be more careful with extensions, because they are the main headache during upgrades. A lot of these ember- libraries we use are just wrappers around other libraries, and I have started to move away from using them, not because of these upgrade issues, but because I’m not that bothered about the sugar these libraries provide and often I just want to access the underlying objects. Also the problem with these ember- wrapper libraries is that they are often using an older version of the library it is wrapping and if they stop being maintained we need to rewrite the code to use the underlying library anyway. In addition to these issues now is the realisation that it is just these ember- libraries that are the problem.

With non ember- libraries we can do an ember upgrade and everything will still work (after we have updated our own code), because the libraries will still import fine and have no ember dependency. Then we can just upgrade these libraries one by one knowing the issue should be isolated to just that library. With ember- libraries you do the ember upgrade and you have to struggle through issues until you finally have the right combination of ember- libraries that work.

Possibly I have raised this discussion in the wrong place and I should be raising issues on the ember- libraries themselves as ember-cli itself is fine and we have never had problems with ember-cli itself.

These are good points.

I agree about not needing ember-specific wrapper libraries anymore. Even when you want to add something ember specific like a helper or component, IMO the addon should list the underlying library as a peerDep and still let the app manage the exact version of it.

The main source of pain is definitely that advanced addons (like ember-concurrency) often reach into private API that isn’t reliable across minor releases. I’m guilty of this myself of course, sometimes it’s the only way, but it does mean you need a higher degree of trust in those addons to help you through updates.