0
votes

I’ve been given a design library from a large cooperate client built utilizing Bootstrap 3 and Require.js. It’s very robust and well-built with the various scripts using Require.js to load jQuery. Problem is, Drupal has already loaded jQuery and the double load is causing some items to fail. If I remove all the Require.js calls, Drupal jQuery stuff works great. If I remove the base Drupal jQuery file, all the stuff using the Require.js stuff works great. Here’ are options I have considered:

  1. Stop jQuery from loading with Drupal, use require to load jQuery on every page - I haven’t tried this yet, but it just seems wrong. I think I can remove jQuery with hook_library_alter() in my theme? Wondering if anyone has tried this… My front end and admin screens actually use 2 different themes, so I think I'd have to modify both.
  2. Stop jQuery from loading with Require.js – I tried this and none of the other libraries that are loaded with require.js can find query if it’s not loaded with Require.js, so I don’t think this option works. This is my first time using require.js so maybe there is some fun fix for this I haven't figured out?
  3. Add all libraries to the site with Drupal – This seems like a lot of messy work as I would have to remove all the require.js dependencies in the library, and there is an expectation that we not modify the library/framework so implementing new releases is easy.

Any other recommendations?

UPDATE per Nikos Paraskevopoulos’ answer:

I have configured Drupal to load the jQuery version that came with the require.js package, and Drupal is happy with that. So now on each page I am loading in the following order:

/components/jquery/jquery.js
/misc/jquery.once.js
/misc/drupal.js
/components/requirejs/require.js
/js/require.config.js

My requires.config looks like this:

requirejs.config({
    baseUrl: "./",
    paths: {
        .....
        jquery:
        "components/jquery/jquery", "jquery-csv": "components/jquery-csv/src/jquery.csv",
        "jqueryui-sortable-amd": "components/jqueryui-sortable-amd/js/jquery-ui-1.10.2.custom",
        .....
    },
    shim: {
        "jquery-backstretch": [
            "jquery"
        ],
        masonry: [
            "jquery"
        ],
        OpenLayers: {
            exports: "OpenLayers"
        },
        "jquery-csv": [
            "jquery"
        ]
    }
});

If I remove the jquery entry from paths, and add:

    jquery: {
        exports: 'jQuery' // NOTE THE CASE OF 'Q', THIS IS THE GLOBAL NAME
    }

I immediately get errors like:

Uncaught Error: Script error for: jqueryui-sortable-amd

Which makes sense as they have all be declared together. uggg.

1

1 Answers

1
votes

Regarding option 2:

I do not know how exactly things load, but I guess Drupal loads jQuery + other stuff it needs, then RequireJS is loaded, which in turn loads its own version of jQuery + other stuff it needs.

First of all you should ensure that the both Drupal and your RequireJS app can play with the same version of jQuery. Then in your RequireJS configuration shim jQuery, instead of loading it normally, e.g. instead of:

require.config({
    ...
    paths: {
        // REMOVE THIS IF USED (PROBABLY IS)
        jquery: 'lib/jquery-x.y.z'
        ...

Do:

require.config({
    ...
    shim: {
        jquery: {
            exports: 'jQuery' // NOTE THE CASE OF 'Q', THIS IS THE GLOBAL NAME
        }
        ...

Explanation: If jQuery is loaded after RequireJS, it defines itself as jquery (lower-case Q). This is the name used by other modules to depend on jQuery. On the other hand, if it is loaded before RequireJS, it does not define itdelf and you are left with the jQuery (and possibly $) globals. The shim above instructs RequireJS to use the global jQuery variable whenever a module depends on the jquery module, which hopefully achieves what you want, i.e. loading jQuery only through Drupal.