|
| 1 | +- Start Date: 2018-10-07 |
| 2 | +- RFC PR: https://github.com/emberjs/rfcs/pull/386 |
| 3 | +- Ember Issue: (leave this empty) |
| 4 | + |
| 5 | +# Remove jQuery by default |
| 6 | + |
| 7 | +## Summary |
| 8 | + |
| 9 | +This RFC proposes deprecating those public APIs that are coupled to jQuery, and to finally remove them (with an optional |
| 10 | +backport), so Ember apps will be built *by default* without bundling jQuery. |
| 11 | + |
| 12 | +While [RFC294](https://emberjs.github.io/rfcs/0294-optional-jquery.html), which is already implemented, provides |
| 13 | +a way to opt out of jQuery, the intention of this RFC is to push this a step further and essentially move from the |
| 14 | +current "included by default, allow opt out" strategy to "excluded by default, allow opt in". |
| 15 | + |
| 16 | +In that way it is not meant as a replacement of the previous RFC, but rather as a continuation and the logical next step. |
| 17 | + |
| 18 | +## Motivation |
| 19 | + |
| 20 | +### Lean by default |
| 21 | + |
| 22 | +This follows the philosophy of making Ember leaner (or *higher octane* if you want), by deprecating unused or |
| 23 | +non-essential APIs. |
| 24 | +New apps will be smaller and faster by default, while allowing to opt-in into using jQuery when needed. |
| 25 | + |
| 26 | +### Why the current opt-out strategy is not sufficient |
| 27 | + |
| 28 | +The biggest problem in the current opt-out strategy is that many addons still require jQuery. Many of these usages |
| 29 | +seem to be rather "accidental", in that the full power of jQuery is not really needed for the given task, and could be |
| 30 | +rather easily refactored to use only native DOM APIs. But as it is available anyway by default, and it is very convenient, |
| 31 | +authors probably tend to use it without being fully aware of the consequences, that it prohibits jQuery-less builds for |
| 32 | +all its consumers. |
| 33 | + |
| 34 | +In that way the general availability of jQuery *by default* and Ember APIs around it like `this.$()` tend to manifest the |
| 35 | +status quo, the coupling of Ember to jQuery. In fact I could observe an actual *increase* of jQuery usage numbers |
| 36 | +(see below), rather than a decrease, which was an intention of the previous RFC. So it is not only a concern of the core |
| 37 | +Ember library to enable jQuery-less builds, but the whole addon ecosystem has to go through that transition. |
| 38 | + |
| 39 | +In that regard early deprecations will help prevent this accidental use of jQuery on the one side, and on the other side |
| 40 | +for addons that depend on jQuery already they will provide an incentive and a long enough transition period to refactor |
| 41 | +their jQuery usage to use standard DOM APIs. |
| 42 | + |
| 43 | +### jQuery might still be needed |
| 44 | + |
| 45 | +This RFC does not propose to discourage the use of jQuery. There are legitimate cases where you still want to have it. |
| 46 | +And this is also true for addons, especially those that basically wrap other jQuery-based libraries like jQuery plugins |
| 47 | +in an Ember friendly way. For those cases, there should be an *opt-in* path to continue bundling jQuery and to preserve |
| 48 | +the existing APIs around it. This is what the `@ember/jquery` package is meant for. |
| 49 | + |
| 50 | +## Transition path |
| 51 | + |
| 52 | +### Add deprecations |
| 53 | + |
| 54 | +All current public APIs that are coupled to jQuery should be deprecated via the usual deprecation process. |
| 55 | +This specifically involves: |
| 56 | + |
| 57 | +* adding a (universal, non-silenceable) deprecation warning to `Ember.$()` |
| 58 | +* adding a deprecation warning to `this.$()` in an `Ember.Component` |
| 59 | +* adding a deprecation warning to `this.$()` in component integration tests, based on `setupRenderingTest()` |
| 60 | + |
| 61 | +### `this.$()` in old style tests |
| 62 | + |
| 63 | +`this.$()` in tests based on the old `moduleForComponent()` based testing APIs will not be specifically deprecated, |
| 64 | +as these legacy testing APIs will eventually be deprecated altogether, as already envisaged in RFC232. |
| 65 | + |
| 66 | +### Extend `@ember/jquery` package |
| 67 | + |
| 68 | +For apps and addons that have to or choose to still require jQuery, they can add this package to its dependencies. |
| 69 | +This will provide a way to retain the deprecated and later removed APIs. So by adding this to your dependencies this |
| 70 | +would effectively be the way to *opt-in* to require jQuery. |
| 71 | + |
| 72 | +RFC294 already introduced this package, being responsible to include jQuery into the JavaScript bundle. As part of this |
| 73 | +RFC the scope of this addon will be extended to also reintroduce the deprecated APIs, but *without* triggering any |
| 74 | +deprecation warnings for `this.$()` in a component. |
| 75 | + |
| 76 | +As the default `EventDispatcher`, which currently dispatches jQuery events when jQuery is enabled, will eventually |
| 77 | +support native events only (see the Timeline below), the addon also needs to replace it with one that again dispatches |
| 78 | +jQuery events for compatibility with existing jQuery-based code. This can happen in a similar way as |
| 79 | +[ember-native-dom-event-dispatcher](https://github.com/rwjblue/ember-native-dom-event-dispatcher) did it, just the other |
| 80 | +way around. |
| 81 | + |
| 82 | +**This effectively makes the integration of jQuery a feature of this addon, rather than Ember itself, which is freed from |
| 83 | +the burden to care about this.** |
| 84 | + |
| 85 | +So effectively, for the Ember 3.x release cycle, adding this package will not change the behavior in any significant way, |
| 86 | +other than removing the mentioned deprecation warnings, as Ember will still have these APIs available. However starting |
| 87 | +with Ember 4.0, which will have these APIs removed and not include jQuery integration features anymore, this |
| 88 | +package will make sure jQuery remains included and it will add the now removed APIs back again, so any jQuery depending |
| 89 | +code will continue to work just as before. Also see the timeline below. |
| 90 | + |
| 91 | +As `ember-cli-babel` will currently transform `import $ from 'jquery';` to use `Ember.$` again, it must be made aware of |
| 92 | +the `@ember/jquery` package so it tells `babel-plugin-ember-modules-api-polyfill` not to convert those imports to the |
| 93 | +global `Ember.$`. Instead the package itself should provide the necessary shim to make `import $ from 'jquery';` work. |
| 94 | + |
| 95 | +Addons that continue to depend on jQuery would have to list this package as a dependency in their `package.json`, |
| 96 | +to make their consuming app automatically include jQuery and the related APIs in its bundle as mentioned above. |
| 97 | +Thereby they make their dependency on jQuery explicit, which in turn helps users to make an educated choice if they |
| 98 | +deem this to be acceptable. |
| 99 | + |
| 100 | +### Extend ember-fetch |
| 101 | + |
| 102 | +The `ember-fetch` addon integrates the newer [`Fetch API`](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) |
| 103 | +nicely into an Ember app, with an (optional) polyfill for older browsers. This can be used as a replacement for the |
| 104 | +jQuery-based `ember-ajax`. |
| 105 | + |
| 106 | +One piece that is missing so far when switching is a convenient way to customize all outgoing requests, e.g. to add |
| 107 | +HTTP headers for authentication tokens. When using jQuery's AJAX implementation, this could be easily done using its |
| 108 | +[`prefilter`](http://api.jquery.com/jquery.ajaxprefilter/) function. To facilitate something similar when using |
| 109 | +`ember-fetch`, the addon should be extended with an appropriate API, e.g. by adding a simple service through which |
| 110 | +fetch requests are issued, which provides similar features for customization. The exact API of such a service is however |
| 111 | +out of scope for this RFC. |
| 112 | + |
| 113 | +### Make ember-data use ember-fetch |
| 114 | + |
| 115 | +It must be ensured that all parts of the core Ember experience work flawlessly without jQuery. Currently `ember-data` |
| 116 | +is still relying on jQuery for its XHR requests. By the time this RFC is implemented (i.e. the deprecation messages are |
| 117 | +added), it must work out of the box without jQuery. |
| 118 | + |
| 119 | +Fortunately [migration efforts](https://github.com/emberjs/data/pull/5386) are well advanced to support the `fetch` API |
| 120 | +through `ember-fetch`, so we can expect that to land soon enough that it does not block the transition. |
| 121 | + |
| 122 | +### Update app blueprint |
| 123 | + |
| 124 | +The blueprint to create a new app with `ember new` should be updated to not use jQuery by default. This involves to |
| 125 | +* disable jQuery integration by default (in `config/optional-features.json`) |
| 126 | +* remove the `@ember/jquery` package |
| 127 | +* replace `ember-ajax` with `ember-fetch` |
| 128 | +* add the [`no-jquery`](https://github.com/ember-cli/eslint-plugin-ember/blob/master/docs/rules/no-jquery.md) rule to the |
| 129 | +default ESLint config |
| 130 | + |
| 131 | +### Timeline |
| 132 | + |
| 133 | +During Ember 3.x: |
| 134 | +1. migrate the jQuery integration features to the `@ember/jquery` package |
| 135 | +2. update the blueprints as stated above |
| 136 | +3. add deprecation warnings as stated above |
| 137 | + |
| 138 | +Upon Ember 4.0 |
| 139 | +* remove deprecated functions |
| 140 | +* remove the jQuery specific code paths in the `EventDispatcher` |
| 141 | + |
| 142 | +## How we teach this |
| 143 | + |
| 144 | +As part of the efforts to make jQuery optional, the guides have already been updated to have all examples teach native |
| 145 | +DOM APIs instead of jQuery, and the new testing APIs. |
| 146 | +The [jQuery migration guide](https://guides.emberjs.com/release/configuring-ember/optional-features/#toc_jquery-integration) |
| 147 | +already mentions the APIs that are not available anymore without jQuery and how to opt-out now. |
| 148 | + |
| 149 | +Activating the `no-jquery` ESLint rule will warn developers about any usages of the jQuery-based APIs being deprecated |
| 150 | +here. |
| 151 | + |
| 152 | +The newly added deprecation messages should link to a deprecation guide, which will provide details on how to silence |
| 153 | +these deprecations, either by using native DOM APIs only or by installing `@ember/jquery` to explicitly opt-in into |
| 154 | +jQuery. |
| 155 | + |
| 156 | +For apps the tone of it should be neutral regarding jQuery itself, in the sense that using jQuery is neither |
| 157 | +bad nor good by itself. It depends on the context of the app if using jQuery makes sense or not. It is just that *Ember* |
| 158 | +does no need it anymore, so it is not part of the default Ember experience anymore. |
| 159 | + |
| 160 | +For addons the story is a bit different, in that they are not aware of their app's context, so they should abstain from |
| 161 | +using jQuery if possible. See the [Motivation](#motivation) chapter above. |
| 162 | + |
| 163 | +## Drawbacks |
| 164 | + |
| 165 | +### Churn |
| 166 | + |
| 167 | +A vast amount of addons still depend on jQuery, so adding the deprecations will add some considerable churn for the addon |
| 168 | +ecosystem. As of writing this, there are: |
| 169 | +* [407 addons](https://emberobserver.com/code-search?codeQuery=Ember.%24) using `Ember.$` |
| 170 | +* [546 addons](https://emberobserver.com/code-search?codeQuery=this.%24&fileFilter=addon%2Fcomponents) using `this.$` in components |
| 171 | +* [994 addons](https://emberobserver.com/code-search?codeQuery=this.%24&fileFilter=tests) using `this.$` in tests |
| 172 | + |
| 173 | +A good amount of that churn can be mitigated by |
| 174 | +* existing codemods that migrate tests |
| 175 | +* having an easy way, given by the `@ember/jquery` package, to opt-in to continue bundling jQuery, and to restore the |
| 176 | +deprecated APIs, so no further refactorings are required |
| 177 | + |
| 178 | +## Alternatives |
| 179 | + |
| 180 | +Stick to the current *opt-out* process. |
| 181 | + |
0 commit comments