Allow rel="preload" on assets

Created on 20 December 2022, about 2 years ago
Updated 19 January 2023, about 2 years ago

We should be able to use rel="preload" on a CSS asset.

dist/main.bundle.css: { attributes: { rel: preload, as: style } }

This doesn't work ; we can't override the default rel="stylesheet" because of the way the attributes are merged in Drupal\Core\Asset\CssCollectionRenderer

    // Defaults for LINK and STYLE elements.
    $link_element_defaults = [
      '#type' => 'html_tag',
      '#tag' => 'link',
      '#attributes' => [
        'rel' => 'stylesheet',
      ],
    ];

    foreach ($css_assets as $css_asset) {
      $element = $link_element_defaults;

      // .....

      // Merge any additional attributes.
      if (!empty($css_asset['attributes'])) {
        $element['#attributes'] += $css_asset['attributes'];
      }

Since $array1 + $array2 is not equal to $array2 + $array1 when those arrays have common keys (https://stackoverflow.com/a/13087814/3493566),
$element['#attributes'] += $css_asset['attributes']; should be
$element['#attributes'] = $css_asset['attributes'] + $element['#attributes']; or
$element['#attributes'] = NestedArray::mergeDeep($element['#attributes'], $css_asset['attributes']);

There's the exact same logic on Drupal\Core\Asset\JsCollectionRenderer but, since there's no default rel attribute, we already can use rel="preload" on JS assets.

📌 Task
Status

Active

Version

9.4

Component
Asset library 

Last updated 1 day ago

No maintainer
Created by

🇫🇷France MacSim

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

  • Assigned to Juanjol
  • Status changed to Needs review almost 2 years ago
  • 🇺🇸United States SocialNicheGuru

    MR available for testing.

  • Status changed to Needs work almost 2 years ago
  • 🇺🇸United States smustgrave

    MR has a failure.

    And the fact it is breaking something makes me think this will need it's own test coverage

  • 🇱🇺Luxembourg B-Prod

    The provided solution does not works well, it leads to merge the "stylesheet" and "preload" values, so we get:
    rel="stylesheet preload"

  • Status changed to Needs review over 1 year ago
  • Open in Jenkins → Open on Drupal.org →
    Environment: PHP 8.1 & MySQL 5.7
    last update over 1 year ago
    Custom Commands Failed
  • 🇮🇳India Ajeet Tiwari

    Kindly review the patch if it works fine.

  • Status changed to Needs work over 1 year ago
  • 🇺🇸United States smustgrave

    Isuse was started in MR and should continue there please.

    Also still needs tests.

  • 🇯🇴Jordan Anas_maw

    Patch in 11 worked for me but it's missing the use statement, here is a new patch, I will update the MR also

  • 🇪🇸Spain Juanjol Navarra

    Please propose changes in MR, don't provide more patches as MR is open.

  • First commit to issue fork.
  • last update over 1 year ago
    29,902 pass, 1 fail
  • @nlisgo opened merge request.
  • 🇬🇧United Kingdom nlisgo

    I've created a test which expresses my understanding of the expected behaviour of CssCollectionRenderer.

    I will look at the AssetResolver and CssCollectionGroup a little closer to understand what the expected behaviour of those should be.

  • last update over 1 year ago
    29,883 pass, 2 fail
  • last update over 1 year ago
    29,909 pass
  • @nlisgo opened merge request.
  • Status changed to Needs review over 1 year ago
  • last update over 1 year ago
    Patch Failed to Apply
  • 🇬🇧United Kingdom nlisgo

    The tests added cover my understanding of the expected behaviour. I have made the minimum changes to fix the failing tests.

  • Status changed to Postponed: needs info over 1 year ago
  • 🇬🇧United Kingdom catch

    I think this might be a duplicate of 🐛 Css aggregation should exclude assets with attributes from preprocessing Postponed: needs info - there's no way to reliably merge different attributes for different css files into one aggregate, the only thing we can do is exclude those files from aggregation.

  • 🇦🇺Australia rikki_iki Melbourne

    It's not a duplicate, I just don't think it's the right approach.

    Preloading wouldn't just be for CSS assets, one also might preload a font file. I think it would be clearer if `preload` has it's own entry in the library system that was separate to css and js. Similarly a preconnect entry could be added at the same time.

    Potential library definition;

    font:
      css:
        base:
          https://fonts.example.com/font-name.css: { type: external, attributes: { fetchpriority: high } }
      preconnect:
        https://fonts.example.com: {}
      preload:
        https://fonts.example.com/font-name-regular.woff2: { as: font, attributes: { type: font/woff2, crossorigin: anonymous } }
        https://fonts.example.com/font-name-bold.woff2: { as: font, attributes: { type: font/woff2, crossorigin: anonymous } }
    

    Then we don't need to worry about aggregation or deep merging arrays. It's very clear to anyone reading the library file that these are separate entries to the actual assets.

  • 🇬🇧United Kingdom catch

    For fonts there is Support prefetch/preload/dns-prefetch in the libraries API Active , but that's not allowing rel="preload"> on any arbitrary asset, it would be much closer to what you suggest in #22. I'm going to close this as a duplicate of that issue. Would be great if you could copy your comment over.

Production build 0.71.5 2024