the code in drupal.js uses jQuery only to use the ready event triggering attachBehaviors. This issues introduce domReady (https://github.com/ded/domready) to provide a way of triggering behaviors without the need to load jQuery. It's straight away the minified version because it's the kind of code we never want to have to look at, like modernizr and html5shim.

  • Drupal.getSelection() is removed, nothing uses it in core. And I haven't seen any contrib code using it either.
  • Drupal.ajaxError is moved to ajax.js, it seemed fair :)
  • Removed freezeHeight, it's code from 2006 because the image field widget made the page jumped around #69786-8: Pave the way for integration of jQuery into core. It's not the case anymore.

Also something seemingly unimportant but is: I got rid of the check for previous versions of the Drupal object (I'm talking about the first line of drupal.js here). There is no way the drupal object should be existing beforehand. Ajax loading you say? it's the whole point of our Way too big ajax requests, we never load a script twice. I'll open a follow-up issue to get rid of all of them.

What does this patch means when you script depend on the drupal library:

Before

your script + 90kb (jQuery) + 3.5kb (drupal.js) of minified, ungzipped JS on the page

After

your script + 740o (domready) + 3kb (drupal.js) of minified, ugzipped JS on the page

Original report

In a couple of files we have utilities that don't have a dependency other than the Drupal object (debounce, annouce soon, etc.) but they have to depend on the drupal library, which has a dependency of jQuery, ensuring nobody will look at it when using streamlined JS.

This patch put all of the API which isn't dependant on jQuery in the drupal.js file. And put all the initialisation (the call to attachbehavior, some wierd ajax-related stuff and messing around with the js class) in the drupal.init.js file.

Liraries have been updated to require the drupal.js and not the whole thing (since they only add a new member on the Drupal object).

Next step is if we want to remove the first line of drupal.init.js and make the global Drupal object not dependant of drupal.init.js

There are still a few things I'm not totally clear on but that's definitely a first step in the right direction. With this patch is you want to use a different loader, run behaviors before or after page load or whatever you only need to override the drupal.ini.js file, which is pretty small considering.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

Wim Leers’s picture

Overall, I like this step. However, I think this causes us to be in a fairly schizophrenic place :)

  • drupal.js does not depend on jQuery anymore, but it depends on drupal.init.js, which depends on jQuery. Which is the most schizophrenic part probably.
  • drupal.js does not depend on jQuery anymore, but for Drupal.attachBehaviors() to be called, it needs jQuery. Is it not feasible to have something like the jQuery.ready event without jQuery?
  • drupal.init.js does 4 things:
    1. Drupal.settings = drupalSettings, which is temporary, and can easily live in drupal.js
    2. Drupal.(un)freezeHeight(), which is very dependent on jQuery, but is only a few LoC. Is it not feasible to rewrite this to not use jQuery? Then it can live in drupal.js.
    3. Setting the "js" classname, which you already converted to not use jQuery. Hence it can live in drupal.js. Furthermore, the "js" class on the "html" element is already being set by Modernizr! So should we even keep it? I guess we should, because sites should be allowed to not load Modernizr and still not break things.
    4. Finally, the "on ready, attach behaviors" thing mentioned above.

Overall, it seems that it might be easier to just make Drupal.js *not* depend on jQuery? Assuming it's possible to refactor items 2 and 4 in the above list to not use jQuery, of course.

nod_’s picture

Basically everything in drupal.init.js is stuff I want to get rid of.

#1, #2 worst case, I'm planning on making a module or something that will get rid of drupal.init.js and it's jquery dep. If we can do it in core, all the better.

#3
1. I'd put all the cruft in drupal.init.js it's clear what needs to go away this way.
2. that's an ajax thing. It's not used anywhere else and I don't think contrib uses it. if it can't be in .init.js then it should be moved to ajax.js
3. that's tricky. We have CSS depending on this class and modernizr is not on every pages like you said. I'd say it's safer to keep.
4. that's tricky. Getting the ready event seems to be painful, just look at what jQuery does, it's pretty ugly i wouldn't want that.

Thanks for getting the discussion going :)

webchick’s picture

During clean-up phase of the release is generally not the point to introduce things that need further clean-up. I'd rather do #1 & #2 in this issue, rather than commit us to a weird state that makes Drupal harder to grok for people.

Jelle_S’s picture

Basically everything in drupal.init.js is stuff I want to get rid of.

#1, #2 worst case, I'm planning on making a module or something that will get rid of drupal.init.js and it's jquery dep. If we can do it in core, all the better.

#3
1. I'd put all the cruft in drupal.init.js it's clear what needs to go away this way.
2. that's an ajax thing. It's not used anywhere else and I don't think contrib uses it. if it can't be in .init.js then it should be moved to ajax.js
3. that's tricky. We have CSS depending on this class and modernizr is not on every pages like you said. I'd say it's safer to keep.
4. that's tricky. Getting the ready event seems to be painful, just look at what jQuery does, it's pretty ugly i wouldn't want that.

Thanks for getting the discussion going :)

4. If all you need is a "domready" function, we could just add a small library. Ded's domready.js looks like a decent one, and according to GitHub is only 0.74kb in the minified version. Yes it would mean adding another js "library" to core, and possibly having duplicate code (well sort of => $(document).ready()), but I think the benefit is large enough to at least consider it (0.74kb vs 92kb for jquery-1.9.1.min.js). This way we can have a decent cross-browser ready event, without having to figure it out ourselves...

Just my 2 cents.

Wim Leers’s picture

#3: Indeed. This is a small patch anyway, so it wouldn't hurt to do it all in one patch.
#4: Thanks — that's very useful :)

nod_’s picture

Ok, domReady looks good, here is a patch adding it. The minified version because we never want to have a look at it, like modernizr and html5shim. I don't need the drupal.init file anymore like that, good.

I deleted the Drupal.getSelection() function, nothing uses it in core. Doesn't looked used on d.o either even with the fancy textarea buttons (that are kinda broken on opera btw).

I moved Drupal.ajaxError to ajax.js, seemed fair :) also moved freezeHeight/unFreezeHeight in there like in previous patch.

Also something seemingly unimportant but is: I got rid of the check for previous versions of the Drupal object (I'm talking about the first line of drupal.js here). There is no way the drupal object should be existing beforehand. Ajax loading you say? it's the whole point of our Way too big ajax requests, we never load a script twice. I'll open a follow-up issue to get rid of all of them.

What does this patch means when you script depend on the drupal library:

Before

your script + 90kb (jQuery) + 3.5kb (drupal.js) of minified, ungzipped JS on the page

After

your script + 740o (domready) + 3kb (drupal.js) of minified, ugzipped JS on the page

Win.

nod_’s picture

with the patch maybe

nod_’s picture

Title: Separate API and initialisation code from drupal.js » Remove jQuery dependency from drupal.js and clean it up

and better title, bear with me it's still 13 in the morning here.

Status: Needs review » Needs work

The last submitted patch, core-js-untangle-drupal.js-1974580-6.patch, failed testing.

nod_’s picture

Status: Needs work » Needs review
FileSize
11.04 KB

Haha I'd just remove this test since that's really not what happens IRL. Anyway "fixed" it.

Wim Leers’s picture

Looks very nice! Any tricky aspects I'm not aware of? :)

seutje’s picture

@@ -1,11 +1,14 @@
-var Drupal = Drupal || { 'behaviors': {}, 'locale': {} };
+var Drupal = { behaviors: {}, locale: {} };

Any particular reason we're not trying to prevent overriding any global Drupal object already present?

Also, it feels very much like "I have a dependency on domReady" actually means "I should probably run in the footer", but I guess that's not an assumption we should be making.

Ideally we'd need something like "domReady is defined as dependency, but another script requires jQuery, so dropping domReady in favor of jQuery", but then we'd need some sort of unified syntax, which would require custom code. But I guess contrib could very well handle that...

nod_’s picture

We're not preventing overriding because it's actually never overridden, it's just useless precaution. We don't do that for Drupal.behaviors.XXX and it works just fine. It's the exact same thing.
If it is actually overriding somewhere, you're not using the Drupal API properly and then you're on your own. That's the point of ajaxPageState.

Yes I though about the domready/jQuery thing, but considering it's less than 1k and we removed Drupal.getSelection and Drupal.AjaxError from drupal.js it balances out. It would be really cool in other places though.

seutje’s picture

figured as much.

I don't have any other questions/objections, but would like to take this for a manual spin.

Should be able to do so later today.

seutje’s picture

Status: Needs review » Needs work
+++ b/core/misc/drupal.jsundefined
@@ -1,11 +1,14 @@
 // Allow other JavaScript libraries to use $.
 jQuery.noConflict();

This will error out when using drupal.js without jQuery, won't it?

nod_’s picture

Status: Needs work » Needs review
FileSize
10.24 KB

haha that was stupid, thanks for catching it :)

Status: Needs review » Needs work

The last submitted patch, core-js-untangle-drupal.js-1974580-16.patch, failed testing.

Wim Leers’s picture

core/misc/domready/ready.min.js is missing from the patch, hence the test failure.

nod_’s picture

Status: Needs work » Needs review
FileSize
11.09 KB

-_-"

seutje’s picture

Status: Needs review » Reviewed & tested by the community

Going once, going twice... Sold! No more AJAX stuff where it doesn't belong!

catch’s picture

Why are freezeHeight and unfreezeHeight moved to ajax.js?

nod_’s picture

The ajax framework is the only thing using them. And I'm pretty sure it's not doing much, I didn't want to remove them and having to test it everywhere.

catch’s picture

OK maybe a follow-up issue to try to remove them? They look generic-ish but if they're only used in one place and not doing anything useful it's worth trying to clean up.

nod_’s picture

Ok checked where it comes from, it's code from 2006 because the image field widget made the page jumped around #69786-8: Pave the way for integration of jQuery into core. It's not the case anymore. I even got my IE8 fired up to test it, works fine.

nod_’s picture

Status: Reviewed & tested by the community » Needs review
Wim Leers’s picture

Status: Needs review » Reviewed & tested by the community
alexpott’s picture

Assigned: Unassigned » Dries

Since we're adding a new javascript library (https://github.com/ded/domready) assigning to Dries to make the call.

In my opinion this fantastic improvement in overall page weight justifies adding the new library.

nod_’s picture

updated the issue summary to reflect what's happening in the patch.

droplet’s picture

Is it safe to use above domready script in Drupal ?
https://github.com/jquery/jquery/blob/master/src/core.js#L799
https://github.com/ded/domready/issues/14

I assumed you going to remove jQuery-like stuff, otherwise I see no point to replace it. Everywehre in Drupal using jQuery, doesn't it?

Also, any chance add unload support to drupal_add_library ??
half of sites loading jQuery. (http://trends.builtwith.com/javascript/jQuery)
(another half may load other scripts, eg. Dojo)
Is that means 50% Drupal site loading extra 1kb + 1 extra http request?

Dries’s picture

I'm not sure I fully understood droplet's comment in #29 but it seems like it could be an important point. It sounds like droplet is suggesting that this may cause an extra HTTP request for many sites. If so, we should certainly discuss this more.

catch’s picture

Sites with js aggregation enabled (which should be every production site) won't get an extra HTTP request.

The 1kb of extra js I think is fine given it's going to result in a 90kb reduction for most pages without jQuery loaded - which is going to include a lot of real sites in the wild if we get the js refactoring in core right.

nod_’s picture

Also, any chance add unload support to drupal_add_library ??

Correct me if I'm wrong droplet but you're talking about replacing one library when another one is loaded ? For example replacing domready with a 1 line polyfill that uses jQuery to provide the domready functionality when the domready library is used and you have jQuery used also?

That's something we'd need in at least 3 more places so I'm hoping we can get that working at some point.

xjm’s picture

Dries’s picture

Assigned: Dries » Unassigned

Thanks for the explanations. I'm comfortable with this patch being committed so I'm un-assigning it from myself. The patch does not appear to apply anymore so I'm asking for a retest.

Status: Reviewed & tested by the community » Needs work

The last submitted patch, core-js-untangle-drupal.js-1974580-24.patch, failed testing.

nod_’s picture

Status: Needs work » Needs review
FileSize
11.42 KB

reroll

readyventure’s picture

Indeed. This is a easy patch, so it wouldn't hurt to do it all in one patch.

Thanks I'm new to Drupal

nod_’s picture

Ok I couldn't test the patch in #36 when I made it. Tested it now, works as expected.

alexpott’s picture

Title: Remove jQuery dependency from drupal.js and clean it up » Change notice: Introduce domReady to remove jQuery dependency from drupal.js and clean it up.
Priority: Normal » Critical
Status: Needs review » Active
Issue tags: +Needs change record

Committed 235142a and pushed to 8.x. Thanks!

alexpott’s picture

Just realised that I accidentally committed this from "needs review"... but in my defence... #36 was a re-roll and it was rtbc'd in #26 and signed off by Dries... sorry everyone.

nod_’s picture

Removing two leftover lines that are moved from drupal.js to ajax.js

droplet’s picture

nod_’s picture

nod_’s picture

@droplet the way we're using domready I don't think we'll run into much troubles.

I asked the maintainer of domready about using it in Drupal, told me it's fine https://twitter.com/ded/status/329619860743131138 . If there really are big and unsolavble issues we can still replace the whole domready file by domready = jQuery(document).ready;.

I'll try spending some time with D8 on IE9 see if I can hit an edge case somehow.

nod_’s picture

Title: Change notice: Introduce domReady to remove jQuery dependency from drupal.js and clean it up. » Introduce domReady to remove jQuery dependency from drupal.js and clean it up.
Priority: Critical » Normal
Status: Active » Fixed

Here is the change notice: https://drupal.org/node/1994482

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.

xjm’s picture

Issue tags: -Needs change record

Untagging. Please remove the "Needs change notification" tag when the change notice task is complete.

xjm’s picture

Issue summary: View changes

update issue summary