diff --git a/core/assets/scaffold/files/example.settings.local.php b/core/assets/scaffold/files/example.settings.local.php index 7cb0e68577..143cb5e34a 100644 --- a/core/assets/scaffold/files/example.settings.local.php +++ b/core/assets/scaffold/files/example.settings.local.php @@ -48,6 +48,18 @@ */ $config['system.logging']['error_level'] = 'verbose'; +/** + * Aggressive CSS and JavaScript aggregate cache busting. + * + * Drupal's CSS and JavaScript aggregation is regenerated based on changes to + * library definitions, not on the files themselves. This means that if files + * are changed without the library version being incremented, it usually takes + * some time before the aggregate files themselves are updated. By setting this + * option, CSS and JavaScript aggregates are regenerated on every cache + * clear. + */ +$settings['css_js_aggregate_hash_query_string'] = TRUE; + /** * Disable CSS and JS aggregation. */ diff --git a/core/lib/Drupal/Core/Asset/AssetGroupSetHashTrait.php b/core/lib/Drupal/Core/Asset/AssetGroupSetHashTrait.php index 1d805b4c32..2a80357fe2 100644 --- a/core/lib/Drupal/Core/Asset/AssetGroupSetHashTrait.php +++ b/core/lib/Drupal/Core/Asset/AssetGroupSetHashTrait.php @@ -37,6 +37,10 @@ protected function generateHash(array $group): string { foreach ($group['items'] as $key => $asset) { $normalized['asset_group']['items'][$key] = array_diff_key($asset, $group_keys, $omit_keys); } + if (Settings::get('css_js_aggregate_hash_query_string')) { + // Add the css_js_query_string so that cache clears force a new filename. + $normalized['css_js_query_string'] = $this->state->get('system.css_js_query_string', 0); + } // The asset array ensures that a valid hash can only be generated via the // same code base. Additionally use the hash salt to ensure that hashes are // not re-usable between different installations. diff --git a/core/modules/system/src/Controller/AssetControllerBase.php b/core/modules/system/src/Controller/AssetControllerBase.php index 620b2ecccf..f495e408a8 100644 --- a/core/modules/system/src/Controller/AssetControllerBase.php +++ b/core/modules/system/src/Controller/AssetControllerBase.php @@ -11,6 +11,7 @@ use Drupal\Core\Asset\AttachedAssets; use Drupal\Core\Asset\AttachedAssetsInterface; use Drupal\Core\Asset\LibraryDependencyResolverInterface; +use Drupal\Core\State\StateInterface; use Drupal\Core\StreamWrapper\StreamWrapperManagerInterface; use Drupal\Core\Theme\ThemeInitializationInterface; use Drupal\Core\Theme\ThemeManagerInterface; @@ -81,6 +82,8 @@ abstract class AssetControllerBase extends FileDownloadController { * The asset collection optimizer. * @param \Drupal\Core\Asset\AssetDumperUriInterface $dumper * The asset dumper. + * @param \Drupal\Core\State\StateInterface $state + * The state service. */ public function __construct( StreamWrapperManagerInterface $streamWrapperManager, @@ -91,6 +94,7 @@ public function __construct( protected readonly AssetCollectionGrouperInterface $grouper, protected readonly AssetCollectionOptimizerInterface $optimizer, protected readonly AssetDumperUriInterface $dumper, + protected readonly StateInterface $state, ) { parent::__construct($streamWrapperManager); $this->fileExtension = $this->assetType; diff --git a/core/modules/system/src/Controller/CssAssetController.php b/core/modules/system/src/Controller/CssAssetController.php index 76d1e8a8b7..5c7d428c7d 100644 --- a/core/modules/system/src/Controller/CssAssetController.php +++ b/core/modules/system/src/Controller/CssAssetController.php @@ -38,6 +38,7 @@ public static function create(ContainerInterface $container) { $container->get('asset.css.collection_grouper'), $container->get('asset.css.collection_optimizer'), $container->get('asset.css.dumper'), + $container->get('state'), ); } diff --git a/core/modules/system/src/Controller/JsAssetController.php b/core/modules/system/src/Controller/JsAssetController.php index 221f53410d..5fa5992455 100644 --- a/core/modules/system/src/Controller/JsAssetController.php +++ b/core/modules/system/src/Controller/JsAssetController.php @@ -38,6 +38,7 @@ public static function create(ContainerInterface $container) { $container->get('asset.js.collection_grouper'), $container->get('asset.js.collection_optimizer'), $container->get('asset.js.dumper'), + $container->get('state'), ); } diff --git a/sites/example.settings.local.php b/sites/example.settings.local.php index 7cb0e68577..143cb5e34a 100644 --- a/sites/example.settings.local.php +++ b/sites/example.settings.local.php @@ -48,6 +48,18 @@ */ $config['system.logging']['error_level'] = 'verbose'; +/** + * Aggressive CSS and JavaScript aggregate cache busting. + * + * Drupal's CSS and JavaScript aggregation is regenerated based on changes to + * library definitions, not on the files themselves. This means that if files + * are changed without the library version being incremented, it usually takes + * some time before the aggregate files themselves are updated. By setting this + * option, CSS and JavaScript aggregates are regenerated on every cache + * clear. + */ +$settings['css_js_aggregate_hash_query_string'] = TRUE; + /** * Disable CSS and JS aggregation. */