Commit 5d3a761e authored by alexpott's avatar alexpott

Issue #2506369 by catch, dawehner, Wim Leers: Cache CSS/JS asset resolving

parent d305a8ef
......@@ -1318,7 +1318,7 @@ services:
arguments: ['@library.discovery']
asset.resolver:
class: Drupal\Core\Asset\AssetResolver
arguments: ['@library.discovery', '@library.dependency_resolver', '@module_handler', '@theme.manager']
arguments: ['@library.discovery', '@library.dependency_resolver', '@module_handler', '@theme.manager', '@language_manager', '@cache.data']
info_parser:
class: Drupal\Core\Extension\InfoParser
twig:
......
......@@ -175,7 +175,7 @@ protected function ajaxRender(Request $request) {
// Resolve the attached libraries into asset collections.
$assets = new AttachedAssets();
$assets->setLibraries(isset($this->attachments['library']) ? $this->attachments['library'] : [])
->setAlreadyLoadedLibraries(isset($ajax_page_state) ? explode(',', $ajax_page_state['libraries']) : [])
->setAlreadyLoadedLibraries(isset($ajax_page_state['libraries']) ? explode(',', $ajax_page_state['libraries']) : [])
->setSettings(isset($this->attachments['drupalSettings']) ? $this->attachments['drupalSettings'] : []);
$asset_resolver = \Drupal::service('asset.resolver');
$css_assets = $asset_resolver->getCssAssets($assets, $optimize_css);
......
......@@ -825,6 +825,27 @@ function hook_library_info_build() {
return $libraries;
}
/**
* Modify the JavaScript settings (drupalSettings).
*
* @param array &$settings
* An array of all JavaScript settings (drupalSettings) being presented on the
* page.
* @param \Drupal\Core\Asset\AttachedAssetsInterface $assets
* The assets attached to the current response.
*
* @see \Drupal\Core\Asset\AssetResolver
*
* The results of this hook are cached, however modules may use
* hook_js_settings_alter() to dynamically alter settings.
*/
function hook_js_settings_build(array &$settings, \Drupal\Core\Asset\AttachedAssetsInterface $assets) {
// Manipulate settings.
if (isset($settings['dialog'])) {
$settings['dialog']['autoResize'] = FALSE;
}
}
/**
* Perform necessary alterations to the JavaScript settings (drupalSettings).
*
......
......@@ -158,7 +158,7 @@ protected function getThingsToCheck() {
// Editor.module's JS present. Note: ckeditor/drupal.ckeditor depends on
// editor/drupal.editor, hence presence of the former implies presence of
// the latter.
isset($settings['ajaxPageState']) && in_array('ckeditor/drupal.ckeditor', explode(',', $settings['ajaxPageState']['libraries'])),
isset($settings['ajaxPageState']['libraries']) && in_array('ckeditor/drupal.ckeditor', explode(',', $settings['ajaxPageState']['libraries'])),
// Body field.
$this->xpath('//textarea[@id="edit-body-0-value"]'),
// Format selector.
......
......@@ -130,7 +130,7 @@ function testCommentClasses() {
if ($case['comment_status'] == CommentInterface::PUBLISHED || $case['user'] == 'admin') {
$this->assertIdentical(1, count($this->xpath('//*[contains(@class, "comment")]/*[@data-comment-timestamp="' . $comment->getChangedTime() . '"]')), 'data-comment-timestamp attribute is set on comment');
$expectedJS = ($case['user'] !== 'anonymous');
$this->assertIdentical($expectedJS, isset($settings['ajaxPageState']) && in_array('comment/drupal.comment-new-indicator', explode(',', $settings['ajaxPageState']['libraries'])), 'drupal.comment-new-indicator library is present.');
$this->assertIdentical($expectedJS, isset($settings['ajaxPageState']['libraries']) && in_array('comment/drupal.comment-new-indicator', explode(',', $settings['ajaxPageState']['libraries'])), 'drupal.comment-new-indicator library is present.');
}
}
}
......
......@@ -2053,9 +2053,13 @@ protected function drupalPostWithFormat($path, $format, array $post, $options =
protected function getAjaxPageStatePostData() {
$post = array();
$drupal_settings = $this->drupalSettings;
if (isset($drupal_settings['ajaxPageState'])) {
if (isset($drupal_settings['ajaxPageState']['theme'])) {
$post['ajax_page_state[theme]'] = $drupal_settings['ajaxPageState']['theme'];
}
if (isset($drupal_settings['ajaxPageState']['theme_token'])) {
$post['ajax_page_state[theme_token]'] = $drupal_settings['ajaxPageState']['theme_token'];
}
if (isset($drupal_settings['ajaxPageState']['libraries'])) {
$post['ajax_page_state[libraries]'] = $drupal_settings['ajaxPageState']['libraries'];
}
return $post;
......
......@@ -606,10 +606,46 @@ function system_page_attachments(array &$page) {
}
}
/**
* Implements hook_js_settings_build().
*
* Sets values for the core/drupal.ajax library, which just depends on the
* active theme but no other request-dependent values.
*/
function system_js_settings_build(&$settings, AttachedAssetsInterface $assets) {
// Generate the values for the core/drupal.ajax library.
// We need to send ajaxPageState settings for core/drupal.ajax if:
// - ajaxPageState is being loaded in this Response, in which case it will
// already exist at $settings['ajaxPageState'] (because the core/drupal.ajax
// library definition specifies a placeholder 'ajaxPageState' setting).
// - core/drupal.ajax already has been loaded and hence this is an AJAX
// Response in which we must send the list of extra asset libraries that are
// being added in this AJAX Response.
/** @var \Drupal\Core\Asset\LibraryDependencyResolver $library_dependency_resolver */
$library_dependency_resolver = \Drupal::service('library.dependency_resolver');
if (isset($settings['ajaxPageState']) || in_array('core/drupal.ajax', $library_dependency_resolver->getLibrariesWithDependencies($assets->getAlreadyLoadedLibraries()))) {
// Provide the page with information about the theme that's used, so that
// a later AJAX request can be rendered using the same theme.
// @see \Drupal\Core\Theme\AjaxBasePageNegotiator
$theme_key = \Drupal::theme()->getActiveTheme()->getName();
$settings['ajaxPageState']['theme'] = $theme_key;
// Provide the page with information about the individual asset libraries
// used, information not otherwise available when aggregation is enabled.
$minimal_libraries = $library_dependency_resolver->getMinimalRepresentativeSubset(array_merge(
$assets->getLibraries(),
$assets->getAlreadyLoadedLibraries()
));
sort($minimal_libraries);
$settings['ajaxPageState']['libraries'] = implode(',', $minimal_libraries);
}
}
/**
* Implements hook_js_settings_alter().
*
* Sets values for the core/drupalSettings and core/drupal.ajax libraries.
* Sets values which depend on the current request, like core/drupalSettings
* as well as theme_token ajax state.
*/
function system_js_settings_alter(&$settings, AttachedAssetsInterface $assets) {
// url() generates the script and prefix using hook_url_outbound_alter().
......@@ -647,36 +683,15 @@ function system_js_settings_alter(&$settings, AttachedAssetsInterface $assets) {
if (!isset($settings['pluralDelimiter'])) {
$settings['pluralDelimiter'] = LOCALE_PLURAL_DELIMITER;
}
// Now generate the values for the core/drupal.ajax library.
// We need to send ajaxPageState settings for core/drupal.ajax if:
// - ajaxPageState is being loaded in this Response, in which case it will
// already exist at $settings['ajaxPageState'] (because the core/drupal.ajax
// library definition specifies a placeholder 'ajaxPageState' setting).
// - core/drupal.ajax already has been loaded and hence this is an AJAX
// Response in which we must send the list of extra asset libraries that are
// being added in this AJAX Response.
// Add the theme token to ajaxPageState, ensuring the database is available
// before doing so.
/** @var \Drupal\Core\Asset\LibraryDependencyResolver $library_dependency_resolver */
$library_dependency_resolver = \Drupal::service('library.dependency_resolver');
if (isset($settings['ajaxPageState']) || in_array('core/drupal.ajax', $library_dependency_resolver->getLibrariesWithDependencies($assets->getAlreadyLoadedLibraries()))) {
// Provide the page with information about the theme that's used, so that
// a later AJAX request can be rendered using the same theme.
// @see \Drupal\Core\Theme\AjaxBasePageNegotiator
$theme_key = \Drupal::theme()->getActiveTheme()->getName();
$settings['ajaxPageState']['theme'] = $theme_key;
// Checks that the DB is available before filling theme_token.
if (!defined('MAINTENANCE_MODE')) {
$settings['ajaxPageState']['theme_token'] = \Drupal::csrfToken()->get($theme_key);
$settings['ajaxPageState']['theme_token'] = \Drupal::csrfToken()
->get(\Drupal::theme()->getActiveTheme()->getName());
}
// Provide the page with information about the individual asset libraries
// used, information not otherwise available when aggregation is enabled.
$minimal_libraries = $library_dependency_resolver->getMinimalRepresentativeSubset(array_merge(
$assets->getLibraries(),
$assets->getAlreadyLoadedLibraries()
));
sort($minimal_libraries);
$settings['ajaxPageState']['libraries'] = implode(',', $minimal_libraries);
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment