Problem/Motivation
Backbone JS is used in core by
- contextual links
ckeditor toolbar configurationtour- toolbar
quickedit
However Backbone has only had two releases since 2016, and none since Feb 2019. In addition we're using it in a fashion that is tightly bound to jQuery.
If we're aiming to move away from jQuery by Drupal 10 - should we be evaluating whether Backbone is the right solution for complex core Javascript.
Developers with knowledge of Backbone are few and far between and interest in it is very low
Proposed resolution
Decide if we still want to use Backbone for our complex Javascript in Drupal 10.Decided we no longer want it- If we do decide to then:
Chose an alternative or migrate to something more Vanilla.Port existing code uses in coreDeprecate the core library- Decided on migrating the functionality provided by Backbone to Vanilla JS
- If we decide to stay put, nothing to do.
Remaining tasks
- contextual links: #3203920: Replace Contextual Links BackboneJS usage with VanillaJS equivalent
- ckeditor toolbar configuration Not needed. @zrpnr confirmed that CKEditor5 integration will not include Backbone, so the phasing out of CKEditor 4 will include its use of Backbone.
tour: #3204011: Replace Tour BackboneJS usage with VanillaJS equivalent- toolbar: #3204015: Replace Toolbar BackboneJS usage with VanillaJS equivalent
quickedit: #3204016: Replace Quickedit BackboneJS usage with VanillaJS equivalent- Marking the library internal: #3258931: Deprecate backbone and tag it internal
User interface changes
API changes
Data model changes
Release notes snippet
| Comment | File | Size | Author |
|---|---|---|---|
| #22 | 3145958-22-VANILLA.patch | 92.13 KB | bnjmnm |
| #22 | 3145958-22-VUE.patch | 189.64 KB | bnjmnm |
| #18 | 3145958.-18-vue-prototype-contextual.patch | 188.16 KB | bnjmnm |
| #18 | 3145958.-18-vue-abridged-DO-NOT-TEST.patch | 17.13 KB | bnjmnm |
| #18 | 3145958.-18-vanilla-prototype-tour-contextual.patch | 91.98 KB | bnjmnm |
Issue fork drupal-3145958
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #2
larowlanComment #3
gábor hojtsyWas parented to itself AFAIS.
Comment #4
andypostComment #5
andypostComment #6
wim leers+1
Comment #8
bnjmnmI was curious how Vue might work as a replacement for Backbone so I tried it out on Tour, which seemed like the most simple use of Backbone. This was my first time working with Vue, but I'd spent enough time with React that it wasn't difficult to figure out for something like Tour. Here's some initial thoughts I had regarding the prototype
halve the sizeof tour.es6.js (it's smaller but saying it's halved is inaccurate as the prototype isn't fully documented), so I imagine it would reduce larger uses of Backbone even more, and could probably be used to simplify many non-Backbone JS as well.Comment #9
zrpnrThis is really exciting to see, I was _just_ doing some reading about Vue and thinking about a good place in core to prototype it when I saw your post in #2913628: Proposal to use Vue.js for building Drupal’s administrative UIs !
I haven't looked at the patch in detail yet but I'm looking forward to reviewing this and brushing up on Vue :)
Comment #10
antoniya commented@bnjmnm this is so great, I'm very excited about the fact that you're exploring Vue because I thought most people involved in maintaining core had already set their mind on using React due to.. well, personal preferences. It's a little bit unusual to see it together with jQuery but that's just me (#notabigjqueryfan #vanillajsalltheway).
I love Vue and I use it every time it fits the requirements. Actually, as soon as the designer comes to me and says something like 'I want this and that to fly in from above and then fade out in the direction of the sun, and when the form is submitted I want you to load this huge taxonomy view, but I want everything to happen without a new request to the server bla bla...' – all I can think of are the Vue SFCs I'm about to create for his fancy requirements. 🤩
I'd usually create a REST view for the Drupal data or just pass the relevant JSON response to the FE from a controller or something because there are still a few annoying issues with REST views output. I'm really looking forwards to D10 and a more 'decoupled oriented' approach.
Comment #11
bnjmnmAgree! Fortunately, no new jQuery use was added in that patch, but some existing usage was moved. At the moment Tour depends on a jQuery plugin, but that is being addressed in this issue (which is very far along): #3051766: Deprecate and replace jQuery Joyride (for tours).
A benefit of using some jQuery within Vue for this prototype was it demonstrated how Vue can be implemented incrementally.
Although I'm one of the people involved in maintaining core, those conversations happened before I was in such a role. Based on my understanding of those (pretty lengthy) discussions, adding Vue as a library to replace Backbone and other UI improvements does not necessarily conflict with the React decision. React was the choice for building something brand new & decoupled, but Vue seems useful for addressing several current needs that would need to be addressed even if a React UI option became available.
Comment #12
nod_I can probably offer some context here :) First of all, really nice that it works so "easily". Not a fan of the v- attributes in the PHP but I understand it's a proof of concept.
If we could make it less jQuery-y that'd be great. Curious to see what it'd take to remove jQuery/Backbone from tour (beside the joyride thing), don't worry about the jquery for the .once it's on it's way out.
When the framework discussion happened (drupalcon vienna) we talked about react/preact, vue, angular, ember, elm (that one was quickly off the table). In the end the 4 main frameworks are very similar in what they can technically do so it was not a technically-based decision. The difference was that there were a few people who already knew how to contribute to Drupal core, that were known from the core committers team, and — more importantly — could commit to work on it if we went with React. Personally React wasn't my choice (because facebook, and we were right in the middle of the licence controversy at the time) but I didn't have anything better to propose than what was on the table. There wasn't an obvious "good" choice or an obvious "bad" choice. Perfect is the enemy of good so that's what we went with :)
Nothing in set in stone though. We don't have any of those framework in core so things are still open. The decoupled menus initiative that Dries talked about in his latest keynote is going for react/vue support (more accurately it's framework agnostic with detailed how-tos for a few major frameworks).
@Antoniya please check out the Decoupled menus initiative which is aimed at making life easier for people using drupal the way you do. We need more people on the initiative :)
Comment #13
fgmI use Vue myself when I can too. However, if we are just looking for a way out of Backbone entirely, excluding the option of using it at scale due to React use, maybe Alpine would be a better fit at just 7kB vs 50k or more for Vue.
Comment #14
droplet commenteddual framework isn't cool.
I think Backbone usages in Drupal are over-engineered. Some simple helpers and basic rewrite could deal with over 90% of cases.
For example, extract the main part of tour.js and about 10 lines of plain JavaScript (event listeners). That's all done? Toolbar is pretty much the same way. I only can't comment on Quickedit.
Before you can make the final decision, now you can extract the main logic code out of `Backbone.View.extend` to get a clear view and binding the data model & events soon. No conflicts.
To make it work, you still need the above things (as middleware) to do the communication.
Comment #15
zrpnr@droplet do you mean having both backbone and Vue?
Do you think it would be better to replace Backbone with no framework instead of gradually replacing it with something like Vue?
@fgm Alpine seems like a good potential candidate for replacing backbone/jquery, I haven't used it in a project before but it looks like it has some nice features.
However in the IS one of the stated problems with Backbone is the low interest by the js community. Alpine is very new and comparatively unknown compared to Vue, which has a growing developer base and ecosystem.
Comment #16
larowlanFwiw, I agree with droplet, tour and toolbar could be just vanilla JS
Comment #17
xjmComment #18
bnjmnmI created vanilla and Vue prototypes for contextual links. Both patches have an "abridged" version that removes all changes that aren't really needed for a code review such as library additions and many deleted files. The abridged versions won't work as patches, but they're easier to read.
In both versions, I couldn't find a simple way to replace Backbones collection functionality, so I implemented the contextual links array as a Proxy so it could fire an event when items were added. I'm unsure how to use proxy to fire an event when something is removed or reset, however, so it's not a 1:1 functionality relationship.
Vanilla prototype notes
Vue prototype notes
this.$refsMy subjective takeaways from making these prototypes
Vue pros:
Vue cons:
Vanilla pros:
Vanilla cons:
There's probably plenty in these prototypes that deserve criticism so have at it 🙂. In all honesty I did enjoy working with Vue quite a bit, which makes it all the more important that I provide a Vanilla prototype. It's much easier to argue the merits of an approach when there are examples of the approach! I\
Comment #19
droplet commentedJust a quick scan...
It's easy to compare if you keep the same logic with the same place (filenames)
and mini the changes between two as possible as that can. Let's say......2 random examples...
The Vanilla looks awful. It can be the same
data = () => { return {data}}. Then this part is less important to this comparison.default options (, init point) are diff in 2 builds. It creates extra noise for the comparison I believe.
--------------------
events registered on a different target. (if Vue must do that, jot a note will help)
-------------------------
Also, it will be good if you can create a shared.js and keep common code there.
** Try to use d.org gitlab :) It's easy to link a line (we need look at the full file to get a whole idea)
Sorry! I meant the DrupalCore usages only a simple data object (eg.
data = () => { return {data}}) and simple listen binding. (, while Backbone & Vue build for a more complicated interactive UI)Comment #20
bnjmnmThat's a very good point, I'll look into finding time to refactor them in a way that makes them easier to compare. If Vue looks good it should be based on its capabilities, not because I wrote a messy class 🙂.
Comment #21
antoniya commented@bnjmnm thanks for putting together those prototypes, makes comparisons much easier.
As I've already mentioned, I personally love Vue😍 but I also prefer vanilla JS over jQuery so I'm excited about the change either way.
I see your point about possible Vue edge cases where there might be dependencies on DOM elements/slot content or prop values. Vue does heavy DOM manipulation and that's why sometimes you need to add a line or two in mounted() or provide default values for your props.
Vue nitpick: I probably would have made
updateTriggerText()a computed prop that returns a text value based on the state ofisOpen. Computed props are great for things like that.Comment #22
bnjmnmRefactored to make comparison easier.
Comment #23
effulgentsia commented#2913628-110: Proposal to use Vue.js for building Drupal’s administrative UIs mentions the file size of the Vue library as a concern. #22 uses the
vue.global.prod.jsbuild, which is 106KB unzipped. That can be reduced to 69KB by using thevue.runtime.global.prod.jsbuild, but that excludes the runtime template compiler. Would it be possible to do a PoC of #22 without the need to do runtime template compilation? I.e., instead of settingv-*attributes at runtime, build and precompile a component that we can just change props on at runtime? I have no idea how hard or easy that would be, so feel free to shoot this idea down if it's not worth pursuing.I think that would be worth exploring too. For example, if we could split the vue library into 3 files:
vue.runtime.global.prod.js.vue.global.prod.jsthat isn't invue.runtime.global.prod.js).Then potentially, for simple use cases, like maybe contextual links, all we might need is the core framework. While more advanced use cases could add a dependency on the 2nd and/or 3rd parts.
Meanwhile, we might find that just the core framework is fairly comparable in size to backbone, so swapping one for the other would not add (much) weight relative to the status quo.
Comment #24
larowlanMy personal opinion here.
The presence of this issue, and another to remove Jquery/Jquery UI makes me think that it's clear that if we can do this with Vanilla, then we should.
Aligning our release cycles to other products that move much faster or become redundant has got us in this scenario now, things that get added to core are there for the long haul and hard to remove, even just from core alone - even before you consider BC implications for contrib and client projects.
So whilst I think its cool that it was achievable with Vue I think these reasons, and the inevitable bike-shedding this would trigger (use React, use Vue, use Svelte, everyone has their framework of choice) should be reason enough to just stick with Vanilla
Comment #26
xjmRemoving credit for out-of-scope fork.
Comment #27
justafishI agree with @larowlan. If we were to adopt vue I think we'd also need a holistic evaluation of how it would fit into our entire system, which would be better done once we've got through removing jQuery.
Comment #28
fgmTotally agree with the need for a holistic view, but maybe - just maybe - the completion of jQuery removal would be easier with one of (React|Vue) than with just vanilla JS, to be completely holistic ?
Comment #29
lauriiiIf we think we would like to use a framework, I'm not sure we should wait until we are done with removing jQuery, because that would mean rewriting large parts of our JavaScript twice, rather than once.
Because of that, I support continuing the evaluation of how different JavaScript frameworks would fit our system. #18 is a good start at this. However, we should go into more detail on what the expected changes mean to end users and contrib projects because this mainly focuses on core developers. According to Drupal values and principles, we should prioritize impact.
Comment #30
lauriiiAdding to #29, something we should learn from jQuery UI is that we should keep our dependencies as internal implementation details. That means that we should not mix API's from the JavaScript framework with our own API's. However, a direct dependency from contrib on the framework could be fine.
Comment #31
bnjmnmAfter re-reading the conversation here and additional discussions outside this issue, my conclusion is:
I'm still interested in the possibility of adding Vue to core, but adding Vue probably shouldn't happen here. Since it was confirmed as possible via prototypes, we should replace Backbone usage with VanillaJS
I opened a separate issue to explore the Vue-in-core option further #3201871: Document benefits/drawbacks of adding Vue as a core JS library (this is specifically a new issue to distinguish it from discussion regarding the dormant Decoupled Admin UI efforts)
Some details on my decision:
I added "Needs framework manager review, Needs subsystem maintainer review" to see if there's agreement on this. If so, I'll turn this into a meta and create child issues.
Comment #32
justafishSounds good @bnjmnm 👍
Comment #33
bnjmnmDiscussed with @lauriii and he approved the VanillaJS approach as well, so removing "needs framework manager review". Created #3203920: Replace Contextual Links BackboneJS usage with VanillaJS equivalent for Backbone, and more followups on the way.
Comment #34
bnjmnmComment #35
bnjmnmComment #37
kim.pepperComment #38
nod_While I'm still on the vanilla-js boat, something that might be of interest: https://www.npmjs.com/package/petite-vue
Comment #39
Phil Wolstenholme commentedOn the subject of petit-vue, there is also Alpine.js which is a similar idea but already on its second major release, more widely used than petit-vue, and is one of the maintainer's primary projects, rather than someone that was a fun side project for Evan You.
We've been using it with Drupal for a year or so now and it works really nicely for adding reactive/data-driven behaviour to server-generated HTML.
https://alpinejs.dev/alpine-101
https://www.smashingmagazine.com/2020/03/introduction-alpinejs-javascrip...
Comment #40
fgm@phil see #13 and #15 about Alpine.
Comment #41
effulgentsia commentedI don't know if there's another issue where this has been discussed, but what do folks here think about Svelte? #24 alludes to some of the problems of core using any shipped framework, including aligning release cycles and managing BC. However, because Svelte compiles code, so we wouldn't need to ship it itself, would that address those concerns, while still giving us the benefit of easier to write, maintain, and understand code for handing the things that we currently use Backbone for? That 2nd part would still need to be proven with a side-to-side comparison of Vanilla vs. Svelte for one of our current Backbone usages. But @larowlan and others: what are your thoughts on that first part?
Comment #42
imclean commented@effulgentsia, wouldn't that approach still have a requirement on an external framework (Svelte) for development, whether it's shipped or not?
For Vue.js see also: https://cli.vuejs.org/guide/build-targets.html#web-component
Comment #44
nod_So going back to backbone. It was added to core in the hope that contrib/projects will pick it up. Nowdays it's not what's happening. So we should mark backbone as an internal library (as in we don't expect anyone else to be using it and we don't guarantee our backbone is the same backbone as the one in https://backbonejs.org).
Getting backbone out of the various places it's used we should have a good reason for it to change the APIs we have.
What I think should happen:
That way we can reduce the js footprint, narrow down very specifically what we use for each backbone function/object (essentially we'd do a manual tree shaking), that will allow us to know what is the actual API we provide (our + the lib's API). And we might want to keep that around if it's too disruptif to contrib to change.
What makes things a bit easier than the jQuery stuff is that backbone-backed functionality is mainly used from PHP, so it's much easier to manage BC.
Comment #45
catchI think the route of marking it internal, and then slimming everything down, is a good one here. @lauriii in slack mentioned the possibility of marking some things deprecated in 9.4.x for removal in 10.x (with no replacement), and that's a similar approach we've taken to some internal or internal-ish PHP code too.
Comment #46
xjmSince our original concerns about Backbone, the project has a new maintainer and some recent activity. The (soft) dependency of our Backbone usages on jQuery is also minimal and outside the library itself, so hopefully it should not be too difficult to update APIs for jQuery 4.
I believe the current plan is:
I might have mixed up which of Tour and Toolbar is which; I'm not working on this myself and they both start with "T" so I keep forgetting what others have told me about it. :)
Comment #47
xjmI do have one question. If we mark our Backbone library internal, what should contributed modules that do depend on it do? The normal policy for contrib is that third-party dependencies are not committed to the repo, but have to be installed and maintained manually by the site owner. But wouldn't having two copies of Backbone in a site's codebase lead to... badness?
This will affect the QuickEdit contrib module for sure. What should QuickEdit do?
Comment #48
nod_quickedit will need to use the /libraries folder to reference the backbone file (so in the libraries.yml file put
/libraries/backbone/backbone.min.jsas the asset path. Even if other modules require backbone, as long as they use the libraries path, only one file will be loadehttps://www.drupal.org/node/3099614
The one downside is that we don't have an automated way to download the backbone library in the right place, adding backbone in the right folder is a manual step.
Comment #49
effulgentsia commentedComposer can do it. It requires adding the https://asset-packagist.org repository and specifying where
bower-assetandnpm-assetpackages should be installed. The Composer project templates for Lightning, Thunder, Commerce Kickstart, and I suspect several other Drupal distributions all do this. Then all you need is a"npm-asset/backbone": "^1.4"or"bower-asset/backbone": "^1.4"(depending on where you want to get it from) within the "require" section of whichever module's composer.json needs it.Adding the configuration for https://asset-packagist.org to drupal/recommended-project was rejected in #3198245: Composer script: enable-asset-packagist, and #3198417: Official support for npm is a followup issue to explore if we want to add support for some alternate solution, if we reject the idea of asset-packagist.
Comment #50
fgmAsset Packagist is a quick fix, but mazimizes install time and memory: seconding the idea not to revisit it.
Comment #51
effulgentsia commentedEven if we don't use asset packagist, I think there'd be a lot of benefit to integrating it into the Composer workflow in some way. E.g., webform does it by adding package repositories. This might be getting a bit off topic for this issue, so I found #2873160: Implement core management of 3rd-party FE libraries and added a comment there.
Comment #52
xjmComment #56
catchFrom 11.x onwards we're down to toolbar and contextual links, it makes sense to focus on those. If the contrib modules also remove backbone eventually, we could try to port those changes across to a 10.x minor release for tour too.