Only file JavaScript assets with preprocessing enabled can be optimized.

Created on 23 January 2024, 11 months ago

Problem/Motivation

Error when tries to load asset from google_tag.
The issue can be fixed using a workaround from https://www.drupal.org/project/google_tag/issues/3413105 πŸ› Only file JavaScript assets with preprocessing enabled can be optimized. Active

The website encountered an unexpected error. Please try again later.

Exception: Only file JavaScript assets with preprocessing enabled can be optimized. in Drupal\Core\Asset\JsOptimizer->optimize() (line 34 of core/lib/Drupal/Core/Asset/JsOptimizer.php).
Drupal\Core\Asset\JsCollectionOptimizerLazy->optimizeGroup() (Line: 183)
Drupal\system\Controller\AssetControllerBase->deliver()
call_user_func_array() (Line: 123)
Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}() (Line: 592)
Drupal\Core\Render\Renderer->executeInRenderContext() (Line: 124)
Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->wrapControllerExecutionInRenderContext() (Line: 97)
Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}() (Line: 181)
Symfony\Component\HttpKernel\HttpKernel->handleRaw() (Line: 76)
Symfony\Component\HttpKernel\HttpKernel->handle() (Line: 58)
Drupal\Core\StackMiddleware\Session->handle() (Line: 48)
Drupal\Core\StackMiddleware\KernelPreHandle->handle() (Line: 53)
Asm89\Stack\Cors->handle() (Line: 48)
Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle() (Line: 51)
Drupal\Core\StackMiddleware\NegotiationMiddleware->handle() (Line: 36)
Drupal\Core\StackMiddleware\AjaxPageState->handle() (Line: 55)
Drupal\http_headers_cleaner\Middleware\HttpHeadersCleanerMiddleware->handle() (Line: 51)
Drupal\Core\StackMiddleware\StackedHttpKernel->handle() (Line: 704)
Drupal\Core\DrupalKernel->handle() (Line: 19)

Why the core forces the assets to be minified?

Steps to reproduce

The problem seems to be
If the asset is not minified then it calls to optimize.
\Drupal\Core\Asset\JsCollectionOptimizer::optimize

                // Optimize this JS file, but only if it's not yet minified.
                if (isset($js_asset['minified']) && $js_asset['minified']) {
                  $data .= file_get_contents($js_asset['data']);
                }
                else {
                  $data .= $this->optimizer->optimize($js_asset);
                }

But if the preprocess is set to false, it throws an error, so the optimizers force the asset to be minified, and it gives a 500 Error when tries to load the asset.

\Drupal\Core\Asset\JsOptimizer::optimize

    if (!$js_asset['preprocess']) {
      throw new \Exception('Only file JavaScript assets with preprocessing enabled can be optimized.');
    }

Example from google_tag.libraries.yml

gtag:
  js:
    js/gtag.js: { preprocess: false }
  drupalSettings:
    gtag:
      tagId: null
      otherIds: []
      events: []
  dependencies:
    - core/drupalSettings
πŸ› Bug report
Status

Active

Version

10.1 ✨

Component
Asset libraryΒ  β†’

Last updated about 15 hours ago

No maintainer
Created by

πŸ‡ͺπŸ‡ΈSpain eduardo morales alberti Spain, πŸ‡ͺπŸ‡Ί

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

Merge Requests

Comments & Activities

  • πŸ‡ͺπŸ‡ΈSpain eduardo morales alberti Spain, πŸ‡ͺπŸ‡Ί
  • Status changed to Needs work 11 months ago
  • πŸ‡ͺπŸ‡ΈSpain eduardo morales alberti Spain, πŸ‡ͺπŸ‡Ί
  • πŸ‡ͺπŸ‡ΈSpain eduardo morales alberti Spain, πŸ‡ͺπŸ‡Ί
  • πŸ‡·πŸ‡ΊRussia niklan Russia, Perm

    I'm facing the same issue. I don't understand the current logic. If the library doesn't want to be preprocessed, why is it automatically minified by default? In that case it makes no sense in preprocess: false.

    I believe the issue lies in the logic implemented in two methods: \Drupal\Core\Asset\JsCollectionOptimizerLazy::optimizeGroup and \Drupal\Core\Asset\JsCollectionOptimizer::optimize.

    The \Drupal\Core\Asset\JsCollectionOptimizer::optimize respects asset group preprocess status:

              if (!$js_group['preprocess']) {
                $uri = $js_group['items'][0]['data'];
                $js_assets[$order]['data'] = $uri;
              }
    

    The \Drupal\Core\Asset\JsCollectionOptimizerLazy::optimizeGroup function optimizes the group regardless of any conditions. It doesn't have a condition and simply moves on to the optimization process.

    This method should looks like:

      public function optimizeGroup(array $group): string {
        $data = '';
        $current_license = FALSE;
    
        // No preprocessing, single JS asset: just use the existing URI.
        if ($group['type'] === 'file' && !$group['preprocess']) {
          $data = file_get_contents($group['items'][0]['data']);
        }
        else {
          foreach ($group['items'] as $js_asset) {
            // Ensure license information is available as a comment after
            // optimization.
            if ($js_asset['license'] !== $current_license) {
              $data .= "/* @license " . $js_asset['license']['name'] . " " . $js_asset['license']['url'] . " */\n";
            }
            $current_license = $js_asset['license'];
            // Optimize this JS file, but only if it's not yet minified.
            if (isset($js_asset['minified']) && $js_asset['minified']) {
              $data .= file_get_contents($js_asset['data']);
            }
            else {
              $data .= $this->optimizer->optimize($js_asset);
            }
            // Append a ';' and a newline after each JS file to prevent them from
            // running together.
            $data .= ";\n";
          }
        }
    
        // Remove unwanted JS code that causes issues.
        return $this->optimizer->clean($data);
      }->optimizer->clean($data);
      }
    
  • Status changed to Needs review 7 months ago
  • πŸ‡·πŸ‡ΊRussia niklan Russia, Perm

    I created the MR with the fix and it works with the google_tag module. However, I'm still not sure about this part of the code: $data = file_get_contents($group['items'][0]['data']);. The same code occurs in the methodDrupal\Core\Asset\JsCollectionOptimizer::optimize. It seems that there may be more than one 'item' in the group, and in such a case, some content may be missing. Need some advice here is that safe or not.

  • Pipeline finished with Success
    7 months ago
    Total: 624s
    #192594
  • πŸ‡·πŸ‡ΊRussia niklan Russia, Perm

    It also fails when using libraries with external dependencies, but with a slightly different exception.

    Only file JavaScript assets can be optimized.

    E.g. of such library:

    example:
      version: 1
      remote: https://example.com
      license:
        name: Example
        url: https://example.com/license
        gpl-compatible: true
      js:
        js/init.js: { }
        //example.com/script.js: { preprocess: false }
    

    The suggested solution won't work in this case because the type here is external, which is handled in the method \Drupal\Core\Asset\JsCollectionOptimizer::optimize, but not in the method \Drupal\Core\Asset\JsCollectionOptimizerLazy::optimizeGroup. But for now, I’m out of ideas on how to solve this issue for external libraries. The result of the lazy method should be optimized JavaScript.

    For those who have encountered this problem, I suggest explicitly setting the following in the code: {preprocess: false, minified: true} for such JavaScript files.

    It's also worth mentioning that the solution from MR and Drupal\Core\Asset\JsCollectionOptimizer::optimize does not include injecting library license information.

  • Status changed to Needs work 6 months ago
  • πŸ‡ΊπŸ‡ΈUnited States smustgrave

    Can the issue summary be updated to include any proposed solution and other relevant sections from the issue template.

    Previously was tagged for tests may be good to get those written and may help guide the fix.

  • πŸ‡©πŸ‡ͺGermany Anybody Porta Westfalica

    I can confirm this message keeps on filling our logs on larger projects.

  • πŸ‡ΊπŸ‡ΈUnited States jackfoust

    It appears this is also affecting the Stripe module.

  • πŸ‡ΊπŸ‡ΈUnited States firewaller

    We're seeing this too. Its odd that it would skip "minified" but not "preprocess = false" here if the optimize function is just going to throw an exception for "preprocess = false": https://git.drupalcode.org/project/drupal/-/blob/11.x/core/lib/Drupal/Co...

  • πŸ‡ΊπŸ‡ΈUnited States apotek

    Just reporting in that we are seeing this frequent visitor in our logs too.

  • πŸ‡©πŸ‡ͺGermany J-Lee πŸ‡©πŸ‡ͺπŸ‡ͺπŸ‡Ί

    Same issue here. A larger project fills the log with this error message.

  • πŸ‡©πŸ‡ͺGermany Anybody Porta Westfalica

    This indeed still fills up the logs and is confusing. This is nothing that should be at exception level, I think. For us, it means, that monitoring sees this as (kind of critical) error like the application is broken somewhere. We should really fix this, or at least reduce the severity for that reason. Especially because the site owner can't do anything about it?

  • πŸ‡©πŸ‡ͺGermany Anybody Porta Westfalica

    anybody β†’ changed the visibility of the branch 3416508-only-file-javascript to hidden.

  • Pipeline finished with Failed
    1 day ago
    Total: 506s
    #374745
Production build 0.71.5 2024