(I have looked at related answers, they provide no help because they make invalid assumptions.)

I'm working on a job where the front-end is component-based. I have no control over this. Some of the front-end requires JS and, if it doesn't load last, it screws up all the Drupal JS.

I need to force these three front-end JS files to load last and I would prefer to do it legally.

I have tried hacking the weights in js_alter() but apart from being a bad idea (it's not advised) it does not seem to have any effect.

I've tried setting the weights in the theme.libraries.yml file but it's impossible to set the weights to enforce what I need. (Set them too heavy and you get an exception.)

My final solution is to force the front-end theme library to be dependent on every Drupal library it conflicts with.

This works, BUT it forces the drupal JS to load on pages where it's not needed (because the theme JS is needed on every page*).

Any ideas?

*Technically it's not needed on every page but I am not in a position to request the front-end guys write their code better...

put on hold as unclear what you're asking by Kevin, Pierre.Vriens, mradcliffe, leymannx, Yusef Mohamadi 16 hours ago

Please clarify your specific problem or add additional details to highlight exactly what you need. As it's currently written, it’s hard to tell exactly what you're asking. See the How to Ask page for help clarifying this question. If this question can be reworded to fit the rules in the help center, please edit the question.

  • Is it because they're using their own version of jQuery? – Kevin Dec 4 at 14:55
  • Are you adding these 3 JS files through a module or a theme? – Ismail Cherri Dec 4 at 19:02
  • Kevin - they aren't. It doesn't matter why it's a problem, that's not something I can control. I know what needs to be done to solve it, I just need the best approach. Ismail - they come from the theme because it's a custom theme that uses the components. But that really isn't important. How do I make these JS files load last without using dependencies in the library definition? – Adaddinsane Dec 4 at 20:07
up vote 0 down vote accepted

Turns out I am an idiot.

There were two copies of jQuery so removing the Drupal jQuery and forcing the non-Drupal JS to load first solves the problem completely.

And no massive list of dependencies.

When I first implemented the suggested fix I made a mistake and then assumed it didn't work. Hence my crazy solution with dependencies.

/**
 * Implements hook_js_alter().
 */
function customtheme_js_alter(&$javascript, AttachedAssetsInterface $assets) {
  // Unset default modernizr as custom one is added from Fabric assets.
  unset($javascript['core/assets/vendor/modernizr/modernizr.min.js']);
  // Unset Drupal's jQuery as we aren't using it.
  unset($javascript['core/assets/vendor/jquery/jquery.min.js']);

  // Give build.js the lowest weight.
  $max_weight = 0;
  $min_weight = 0;
  foreach ($javascript as $key => $value) {
    if ($value['weight'] > $max_weight) {
      $max_weight = $value['weight'];
    }
    if ($value['weight'] < $min_weight) {
      $min_weight = $value['weight'];
    }
  }

  // Make modernizer custom run next followed by define-fix. (now in head)
  // Define-fix makes drupal define function calls match Fabric's define.
  if (isset($javascript['themes/customtheme/fabric/dist/scripts/build.js'])) {
    $javascript['themes/customtheme/fabric/dist/scripts/build.js']['weight'] = $min_weight - 1.0;
    $javascript['themes/customtheme/fabric/dist/scripts/modernizr.custom.js']['scope'] = 'header';
    $javascript['themes/customtheme/js/define-fix.js']['weight'] = $min_weight - 0.9998;
  }
}

And for completeness the "define-fix" code is:

defineReal = define;
define = function (name, deps, callback) {
  if(arguments.length === 2 ){
    defineReal(name, [], callback);
  }else{
    defineReal(name, deps, callback);
  }
};

Not the answer you're looking for? Browse other questions tagged or ask your own question.