Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deprecate all of Ember Classic #832

Open
wagenet opened this issue Jul 23, 2022 · 16 comments
Open

Deprecate all of Ember Classic #832

wagenet opened this issue Jul 23, 2022 · 16 comments
Assignees

Comments

@wagenet
Copy link
Member

wagenet commented Jul 23, 2022

@chriskrycho is actively planning to write this RFC so I feel comfortable making an issue here.

While this should not be seen as a comprehensive list, significant effort has been put into discussing the deprecation of classic features and is noted below for incorporation into this future RFC:

@chriskrycho
Copy link
Contributor

Don’t panic, everybody. 😅 This will happen with ample time for migrations! I’m waiting in part to get to a decision on #830, so I can target the deprecations for an appropriately generous timeframe!

@runspired
Copy link
Contributor

I've brought this up with core team members in the past but I think I may as well lay it out here.

Ember can't deprecate classic unless ember-data deprecates it first. We've got a chicken-egg problem and it seems better for ember-data to absorb the break first because otherwise it has to somehow support ember both with and without classic support and in doing so would be flooding folks with deprecations they couldn't resolve.

For ember-data to stop using classic APIs we'd have to drop support for classic ourselves, most notably Mixins, Reopen, computed properties, and observers. We began this work with #738 and #793. The rough idea is to break lockstep and target releasing our own major in which we drop support for pre-4.0 ember + all classic ember APIs (e.g. our support matrix will be tighter than simply 4.0 ember, it would also limit what ember we supported to soley the class+tracked world)

@chriskrycho
Copy link
Contributor

(For what it’s worth, I’m one of those members who has had that conversation and I agree. @runspired and I and many others are talking about the path forward here, including multiple discussions at Framework team meetings throughout the spring, and I think we’re getting toward consensus. That RFC will likely need to come before or in parallel with this one.)

@runspired
Copy link
Contributor

We should get the ball moving on "ember-data controls its history / ember-data timeline" though. Roughly we would like to major ember-data around late early December and that would be the release in which we drop support for classic.

@chriskrycho
Copy link
Contributor

Agreed! You and I should sync up next week and work on that!

@runspired
Copy link
Contributor

Not the RFCs, but basically the roadmap for EmberData's next major is now here: emberjs/data#8086

@robbytx
Copy link

robbytx commented Aug 1, 2022

Speaking for all the teams with legacy Ember codebases for which this is going to involve lots of work:

Is there an opportunity for (at least the major parts of) Ember Classic support to be moved into an (intimate) addon, similar to what was done with ember-jquery?

I totally understand the drivers for Ember core to shed itself of Classic, since I imagine removing this support would likely:

  • Remove a substantial amount of code, thereby reducing Ember's page weight
  • Improve (or at least create opportunities to improve) load/render performance
  • Enable future functionality to avoid having to consider how they interop with classic syntax

If this support could be migrated into an addon (a big "if" no doubt), then I feel like you could still reap most of these benefits for new/modern Ember apps, without forcing legacy apps to either rewrite or stagnate. Certainly I imagine Ember core would need to retain some hooks for the classic addon to utilize, so you may not be totally free to change things in core, but I think you could still be free to introduce new, optional functionality that is incompatible with classic, just as there are times when new Ember functionality may be incompatible with existing addons. Maybe it's simply infeasible given current resources, but I feel like if this option were taken, then the changes would be much more readily received by the entire Ember community.

If Ember Classic is simply unsupported in the near future, then this is IMHO akin to the Python 2->3 transition, where every app and addon must either achieve compatibility or effectively die. The Python 2->3 transition lasted for more than a decade, and ultimately required changes in core and the introduction of compatibility libraries, and even then many Python 2 apps and libraries were simply left behind in the process. I recognize that spacing the breaking changes over several major versions (#830) is an attempt to mitigate this problem, but the total effort to get off Classic remains the same (and is potentially larger if you are forced to do it over a period of years) so I'm concerned that we're likely to end up with a similar or worse outcome. Arguably, Python 3 has come through the transition and now reaps the benefits, but it only occurred with lots of effort over a long time from a much larger community, whereas Ember is (like it or not) a much smaller framework in larger JS community. Faced with a need to rewrite much of their app, many teams may simply (and sensibly) choose an more popular web framework than betting on the long-term prospects of Ember community who just left them with an unsupported app.

Admittedly, the last paragraph contains much fear, uncertainty, and doubt, but I really fear that as a likely outcome, so I return to my opening question:

Is there an opportunity for (at least the major parts of) Ember Classic support to be moved into an (intimate) addon?

@wagenet
Copy link
Member Author

wagenet commented Aug 1, 2022

@robbytx Thanks for the detailed feedback. What you've shared is definitely a valid concern and I'm hopeful we can mitigate it. I do think it's possible for at least some of the classic behavior to be moved into addons such as was done with @ember/legacy-built-in-components.

@wagenet
Copy link
Member Author

wagenet commented Aug 1, 2022

@robbytx I should also point out that, unlike migrating to an entirely different library, one can migrate away from Ember Classic incrementally. This is a huge win. I've tried doing "rewrite the world" migrations before and they never go nearly as smoothly at it seems like they will. I have, however, done rewrites from Ember Classic to Octane and, though a non-trivial amount of work, those didn't have any of the major issues that "rewrite the world" has.

@chriskrycho
Copy link
Contributor

I expect this to be one of the main subjects covered by the RFC. Certainly pieces of it will be able to support that, but not all of it. For example it is essential to simply get entirely rid of the classic observers and computed properties; from what I can see, the interoperability story there is either baked into core or it would come with so many caveats that it would require substantial rework anyway… at which point you should just be going to Octane. Likewise, I think we have to completely get rid of classic classes.

That doesn't mean that we have to completely get rid of everything, though. Figuring out what those cut points are, and what can reasonably be pushed into a legacy support ad on and what cannot is one of the major things that I plan to work through as I work on the RFC and discuss it with the community and the Framework team in the months ahead!

Also, look for a blog post from me on the LinkedIn engineering blog sometime this year discussing how we have successfully incrementally migrated the entirety of the flagship app to Octane—millions of lines of code!


A meta point: while I am trying to reassure people a bit here, this issue is not the place to hash out all of these things. The RFC itself is!

@NullVoxPopuli
Copy link
Sponsor Contributor

Idk if it's been mentioned anywhere, but when the usage of prototype-extensions are deprecated and eventually removed from ember-source, I think it'd be good to have a v2 addon re-providing those extensions for those that are not yet ready to migrate away.

For example, when prototype-extensions are deprecated and eventually removed, folks could opt-in to installing a new addon, maybe @ember/prototype-extensions (or @ember/legacy-prototype-extensions to be clear prototype extensions in general is a legacy pattern), and folks could install those extensions in their app.js:

// app/app.js
import '@ember/prototype-extensions/array';

// ...

This side-effecting import would install the array prototype extensions, and there is no need for build-time transforms because with v2 addons, stuff that's not imported is not included in the build.

@KroneckerDeIta
Copy link

At our company we have many projects written in Ember and we are diligent in updating our products to the latest versions of Ember and it is a few weeks/months of effort every year for one person. The effort required to upgrade our projects has resulted in my company discussing other frameworks we could move to, but we agree that we have so much code written in Ember that moving to another framework would not be cost effective. We try and migrate over to new style classes, etc. when we can, but 95+% of our codebase is still legacy and if EmberObjects, classic components were ever removed then that would cost our company lots of money in terms of migration effort and at that point we would probably stick with the last version of Ember that would support classic objects and components and move to another framework.

If we could continue to use an addon as @robbytx suggested and that worked for a long time then that would be fine, but I worry that addon would just become unmaintained and stagnant (especially as there probably wouldn't be any drive from the core team to maintain it).

Maybe that is just our company though, in which case there isn't anything for you guys to worry about when deprecating this classic functionality, but I would be interested to know if there were more people with similar experiences/thoughts at their companies.

Sorry to be negative about this. I will say that I very much appreciate the effort the core Ember team puts into maintaining and improving Ember for all these years. It is a great framework.

@robbytx
Copy link

robbytx commented Oct 31, 2023

Having now migrated several of my apps to Octane either fully or partly over the past year, the biggest challenge I've encountered is migrating off of Mixins. Chris' post on the best way to replace mixins has been very helpful in this regard, but the unfortunate point of that post is that migrating off of mixins requires carefully considering the purpose of each mixin and how best to achieve the same purpose using one (or more) of several different alternatives.

Outside of mixins however, I've found there are fairly straightforward alternatives for other classic functionality that one can reach for without much thinking:

  • Observers can typically be replaced with a {{did-update this.observerFunction this.observedProperty}} modifier from ember-render-modifiers (despite its warning against doing so).
  • Computed properties can typically be replaced by a native getter with the @dependentKeyCompat decorator, and optionally the @cached modifier (available before Ember 4.5 from ember-cached-decorator-polyfill).
  • ObjectProxy, PromiseProxyMixin etc are still available in the latest Ember releases, and could conceivably be moved into an ember addon or other library for the future. The same goes for Ember Array and other prototype extensions, as well as events.
  • The native class codemod works well for converting to native class syntax (assuming you have no mixins).
  • The classic-decorator-hooks and classic-decorator-no-classic-methods ESLint rules can then flag any classic API usages that need to be changed.
  • If you've dealt with the above, then the classic->Glimmer component migration mostly just requires using this.args.parameter rather than this.parameter and passing a function down (using @setParameter={{set this "parameter"}}) to components that expect to be able to modify parameters they are provided.

Now I'm not saying this is all low effort, or that there aren't more ideal solutions, but these transformations (again outside of migrating Mixins) are fairly mechanical. They can also be performed component-by-component/class-by-class/even property-by-property as desired until you arrive at a state where you have all native classes and no classic components.

@EWhite613
Copy link

EWhite613 commented Nov 7, 2023

@KroneckerDeIta we're in the same boat.

IMO Ember.js's saving grace was that it had a mantra of "Leave no one behind" and backwards compatibility.

This was great for 2.x - Octane; lots of codemods (which you didn't necessarily have to run, it just put you in a better position for the future), generally you could just opt-in/opt-out, the amount of things you had to change wasn't a super steep hill to climb (fix double renders pretty much) and could leave the rest of your stuff as-is for the most part.

With 4.0/5.0-beyond it's a lot of leaving people stuck in the mud I find and slowly lost the old mantra of "Leave no one behind" and backwards compatibility. Where there's so much effort on the consumer it begins to have us contemplate if that cost is better spent on a framework switch. There's a lot of just run the codemod, but these aren't perfect and require manual intervention and mainly require us to heavily regression test things it touches.

@NullVoxPopuli
Copy link
Sponsor Contributor

Hello! I appreciate you sharing your concern(s)!

With 4.0/5.0-beyond it's a lot of leaving people stuck in the mud

Do you feel this stems from ember-data? or other things? (ecosystem?, unmaintained addons?)

For ember-source, much of what was removed was from the 1.x days.
For a codemod to be able to work, there needs to be a 1 to 1 replacement -- whicch isn't always how things move forward.

contemplate if that cost is better spent on a framework switch

fwiw, some other frameworks don't even have a deprecation system.

There's a lot of just run the codemod, but these aren't perfect and require manual intervention and mainly require us to heavily regression test things it touches

The most common thing I've seen folks get stuck on here is that their node is too far behind -- like, using ?. in the codemod won't work if your local node isn't new enough.

Would love to help folks dive in to getting their migrations across the line! let's chat in the discord! <3

@EWhite613
Copy link

EWhite613 commented Nov 7, 2023

I think we need more backwards polyfills at least like @robbytx suggested in order to not leave anyone behind (and to broadcast these in upgrade guides, as sometimes I'll randomly find one I've never seen talked about). This would go a long way.

Unmaintained addons has a part, but not a huge issue if we stick to more streamlined stuff (sometimes we do have to fork to fix unmaintained repos). I think a lot of it is the sheer amount of removals it's hard hill to climb over. Since this framework handles so much and deprecates a lot. To go from 3.x to newer you have to adjust a lot of things. And you can't really individually move Ember and Ember Data (I know people say you can, but I've tried and it never works until I have both aligned in my case. I get very strange errors) , so that just compounds the amount you need to change.

The most common thing I've seen folks get stuck on here is that their node is too far behind -- like, using ?. in the codemod won't work if your local node isn't new enough.

We've never had this problem. Think I hit once with an old codemod, and just ran the codemod with a newer node on my repos (that had an older node) without issue.

I think codemods are fantastic on stuff you want and can afford to keep current. But on old legacy code we rarely interact with it's a hard thing to get investment into. And that presents a problem cause we want new features in that area, but don't necessarily want to update all the other components (or not the team that owns it. So scheduling is a big task). All that to say solely relying on consumers to run that codemod (which is a lot of work with big ecosystems) may be the pain point here. A polyfill that you put first than slowly run codemods on areas till you eventually can remove polyfill is a much smoother transition and can do incrementally.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants