emberjs / data

A lightweight reactive data library for web applications. Designed over composable primitives.
https://api.emberjs.com/ember-data/release
Other
3.03k stars 1.33k forks source link

Migrate away from jQuery #4929

Closed cibernox closed 6 years ago

cibernox commented 7 years ago

This might deserve an RFC, but for now I want to start the discussion as a mere issue.

I've been trying to make jQuery be optional in Ember apps and so far is going ok. ember-native-dom-event-dispatcher makes Ember itself be jQuery-less. ember-native-dom-helpers provides arternative test helpers that allow to test apps without the jQuery-based helpers provided by Ember. For the most of it, you can replace ember-ajax with ember-fetch with a relatively low effort.

The main blocker for apps is that many addons rely on jQuery and that might block the effort. If just the top 20 of the most popular addons working without jQuery, the rest of the ecosystem would follow.

Of the top 20, ember-data is by far the biggest and more used, and one of the few where removing jQuery is actually a hard task, but that is what I'm proposing here.

Replace $.ajax with fetch

The good news is that I tried and it's not that hard.

By no means this snippet is the full solution, it only works for GET requests and doesn't honor headers and such, but after some digging I have good and bad news, but mostly good:

The fetch API could be conditionally polyfilled using the new targets feature in ember-cli 2.13. Once minified and gzipped it's just ~2KB, so even if included it's footprint is rather small.

Benefits

Downsides

/cc @stefanpenner @runspired @rwjblue @bmac

stefanpenner commented 7 years ago

The fetch API could be conditionally polyfilled using the new targets feature in ember-cli 2.13. Once minified and gzipped it's just ~2KB

thats smaller then jQuery ;)

sandstrom commented 7 years ago

I think it's been proposed at various times to use either ember-ajax (https://github.com/emberjs/data/issues/4175) or ember-network as the network library for Ember Data (though ember-network may be replaced by ember-fetch, plus it's scope is quite limited, so ember-ajax may be the better candidate here).

The benefit being that authentication, custom headers, etc. can be setup once and used both for XHRs originating from Ember Data, for XHRs in other addons and for application-specific XHRs.

As a way of replacing $.ajax I'd suggest making either of the two addons above run without jQuery, and then use them as a network addon for Ember Data. Thoughts?

Also related: https://github.com/emberjs/data/pull/4406 https://github.com/emberjs/data/issues/4404


I'm not against the idea of removing jQuery, on the contrary I'm very supportive. Just wanted to mention some thoughts on how $.ajax can be removed.

jherdman commented 7 years ago

The benefit being that authentication, custom headers, etc. can be setup once and used both for XHRs originating from Ember Data, from other addons and for other XHRs.

As a way of replacing $.ajax I'd suggest making either of the two addons above run without jQuey would be a good way forward, and then use them as a network addon for Ember Data. Thoughts?

As one of the maintainers of ember-ajax, I'd like to say that we're amenable, and interested in, such work. It's a goal of ours to be the library upon which Ember Data builds for its network requests.

/cc @alexlafroscia

cibernox commented 7 years ago

@sandstrom I believe that there is some interest in merge ember-network and ember-fetch, since they have the same goals. I believe they should be the same addon (and ember-fetch has the best name IMO) If we could make ember-ajax work with fetch instead of jQuery then seems like it could be posible to merge all three and have a beautifully unified networking story, and ember-data could build on top of that.

I'm all into the idea.

stefanpenner commented 7 years ago

Literally ember-network is copy pasta of ember-Fetch and ember-Fetch predates ember-network and is maintained. So the discussion is between ember-Ajax and ember-Fetch.

I do believe we want to get to real fetch someday. Is there a way we can either unify or make ember-Ajax and ember-fetch be pluggable?

cibernox commented 7 years ago

@stefanpenner Can you check with Tom if we can start by deprecating either ember-fetch or ember-network in favour of the other? That would be a useful first step.

stefanpenner commented 7 years ago

I can once he returns from vacation

alexlafroscia commented 7 years ago

It's a goal of ours to be the library upon which Ember Data builds for its network requests.

This has always been the a plan, but there was never a huge reason to finally make it happen. Maybe this is it.

I always saw the benefit of ember-ajax being that it could provide just the $.ajax implementation once Ember no longer shipped with jQuery by default, so I'm willing to do the work so that the addon pulls that in if needed.

If we could make ember-ajax work with fetch instead of jQuery then seems like it could be posible to merge all three and have a beautifully unified networking story, and ember-data could build on top of that.

I've kicked this idea around a lot and I, personally, don't think it's a good idea. While there is certainly a benefit to having a unified networking story, there are a few problems IMO:

I've always hoped that the Ember community would land on ember-ajax + ember-(network|fetch) (I have no idea which is the "winning" solution at this point) as the go-to tools, based on whether the developer wants to use the "new" fetch API or the $.ajax API that they're used to. However, that does leave a standing question of what Ember Data could/should build on top of.

btecu commented 7 years ago

Just a heads up, github's fetch polyfill does not support IE9.

cibernox commented 7 years ago

@btecu IE9 does work if you have a promise polyfill, and we already ship RSVP with ember. We can make it work.

sandstrom commented 7 years ago

@alexlafroscia These differences are good points! What do you think about these two possible solutions:

Cancel There is work in progress to add cancelation to fetch (details).

A fairly simple solution is to build cancelation into whichever xhr-service we end up using for Ember Data (but that cancelation wouldn't really cancel the request, just ignore the result when it comes back; i.e. it's a cancel from the perspective of the API consumer, but not on the wire).

4xx responses The xhr-service could still reject on 4xx (I think it makes sense to reject on 4xx and 5xx), even though the underlying fetch library resolved.

cibernox commented 7 years ago

@alexlafroscia I think it would be possible for an addon to be based on fetch and still provide an $.ajax-compatible API. The main differences from the top of my head:

Other than cancellation, that I don't know if it's possible with ember-ajax, seems that we can replicate all that on top of fetch in a small enough amount of code to make fetch: service() and ajax: service() be possible with a single addon.

Tech is not foreign to trends and marketing, so I think we should make fetch be the default in the ecosystem. I think that technical reasons aside, people feel like they want use fetch because it's modern, even if it's just a matter or perception and it will make little to none difference for them. Still, perception matters.

tomdale commented 7 years ago

The intent of ember-network was to aggregate isomorphic network implementations into one spot, including jQuery, XMLHttpRequest and others. In practice najax has been "good enough" and now the momentum is behind fetch, so I have no objection to moving the community off ember-network. That said, given that there is broad ecosystem support for isomorphic packages (via the browser package.json field), I recommend we adopt that instead of doing something Ember-specific.

cibernox commented 7 years ago

@tomdale could you elaborate what you mean by that? I'm not familiar with the browser field on package.json so I don't see the role it would play.

rwjblue commented 7 years ago

I believe that @tomdale is actually referring to modules entry point which is what we allow and use in glimmer applications (browser is a somewhat bizarre spec and we do not currently plan to support browser out of the box).

Some "light" reading:

cibernox commented 7 years ago

@rwjblue If i'm reading this right, Tom is suggesting to create a node library that exposes one polyfill for the browser and another for node, so we can just import fetch from 'package-name';, and depending on if the app is in node or browser, it will get the right polyfill.

However this is just part of what I'd expect the addon to provide. I'd expect the addon to provide

We might create a standard non-ember specific package, but for the last three points we might need to create an ember-addon that relies on that package.

tomdale commented 7 years ago

@rwjblue No, that's not exactly what I'm suggesting. The modules field signifies that the target file is authored with ES6 modules, it doesn't indicate which environment it is designed to be run in. The browser field is used for cases like we're hitting here, where you have one implementation that uses Node APIs and another implementation that uses browser APIs.

The whole thing is incoherent because it has evolved organically. It may be on us to try to propose amendments to module/browser etc that better capture the permutations. But as much as possible, I'd like to align our roadmap with the broader JS ecosystem; using fetch universally between the browser and Node is something many people have, so we should try to join forces to tackle the problem.

webark commented 7 years ago

wondering if this got picked up in any ember data sub team meetings.

tomdale commented 7 years ago

@webark Not as far as I know, but I finally got around to deprecating ember-network this weekend and ember-fetch is FastBoot compatible. It seems like the important thing to do is to migrate Ember Data to use fetch semantics via ember-fetch. Once that's working, how we get fetch into Ember Data is just an implementation detail.

There is a lot of interest in getting npm packages consumable in a first-class way. Once that's in, we can probably start to think about even being able to move off ember-fetch and have ED rely on a non-Ember-specific fetch implementation (which ember-fetch is a wrapper around anyway).

RobbieTheWagner commented 7 years ago

Any updates on this? I've been working on removing jQuery from my apps and addons and I think the only major thing holding me back, at this point, is ember-data.

cibernox commented 7 years ago

@rwwagner90 I managed to make ED work without jquery, using https://github.com/ember-cli/ember-fetch#use-with-ember-data

webark commented 7 years ago

@rwwagner90 i've done the same..

runspired commented 6 years ago

Closing in favor of the quest in #5320. We're on our way :)