diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/asset_mapper.php b/src/Symfony/Bundle/FrameworkBundle/Resources/config/asset_mapper.php index 729effe6b5996..296358cfcf72c 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/asset_mapper.php +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/asset_mapper.php @@ -174,6 +174,7 @@ param('kernel.charset'), abstract_arg('polyfill URL'), abstract_arg('script HTML attributes'), + service('request_stack'), ]) ->set('asset_mapper.importmap.auditor', ImportMapAuditor::class) diff --git a/src/Symfony/Component/AssetMapper/CHANGELOG.md b/src/Symfony/Component/AssetMapper/CHANGELOG.md index b7402e73e7d34..012dde82a8a26 100644 --- a/src/Symfony/Component/AssetMapper/CHANGELOG.md +++ b/src/Symfony/Component/AssetMapper/CHANGELOG.md @@ -9,6 +9,7 @@ CHANGELOG * Add "entrypoints" concept to the importmap * Always download packages locally instead of using a CDN * Allow relative path strings in the importmap + * Automatically set `_links` attribute for preload CSS files for WebLink integration * Add `PreAssetsCompileEvent` event when running `asset-map:compile` * Add support for importmap paths to use the Asset component (for subdirectories) * Removed the `importmap:export` command diff --git a/src/Symfony/Component/AssetMapper/ImportMap/ImportMapRenderer.php b/src/Symfony/Component/AssetMapper/ImportMap/ImportMapRenderer.php index 00d48fe71949f..8e54da6c0ba60 100644 --- a/src/Symfony/Component/AssetMapper/ImportMap/ImportMapRenderer.php +++ b/src/Symfony/Component/AssetMapper/ImportMap/ImportMapRenderer.php @@ -11,7 +11,13 @@ namespace Symfony\Component\AssetMapper\ImportMap; +use Psr\Link\EvolvableLinkProviderInterface; use Symfony\Component\Asset\Packages; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\RequestStack; +use Symfony\Component\WebLink\EventListener\AddLinkHeaderListener; +use Symfony\Component\WebLink\GenericLinkProvider; +use Symfony\Component\WebLink\Link; /** * @author Kévin Dunglas @@ -27,6 +33,7 @@ public function __construct( private readonly string $charset = 'UTF-8', private readonly string|false $polyfillUrl = ImportMapManager::POLYFILL_URL, private readonly array $scriptAttributes = [], + private readonly ?RequestStack $requestStack = null, ) { } @@ -68,6 +75,10 @@ public function render(string|array $entryPoint, array $attributes = []): string $output .= "\n"; } + if (class_exists(AddLinkHeaderListener::class) && $request = $this->requestStack?->getCurrentRequest()) { + $this->addWebLinkPreloads($request, $cssLinks); + } + $scriptAttributes = $this->createAttributesString($attributes); $importMapJson = json_encode(['imports' => $importMap], \JSON_THROW_ON_ERROR | \JSON_PRETTY_PRINT | \JSON_UNESCAPED_SLASHES | \JSON_HEX_TAG); $output .= << new Link('preload', $url), $cssLinks); + + if (null === $linkProvider = $request->attributes->get('_links')) { + $request->attributes->set('_links', new GenericLinkProvider($cssPreloadLinks)); + + return; + } + + if (!$linkProvider instanceof EvolvableLinkProviderInterface) { + return; + } + + foreach ($cssPreloadLinks as $link) { + $linkProvider = $linkProvider->withLink($link); + } + + $request->attributes->set('_links', $linkProvider); + } } diff --git a/src/Symfony/Component/AssetMapper/Tests/ImportMap/ImportMapRendererTest.php b/src/Symfony/Component/AssetMapper/Tests/ImportMap/ImportMapRendererTest.php index 550d56fc6a1b2..d9f5653b9b38b 100644 --- a/src/Symfony/Component/AssetMapper/Tests/ImportMap/ImportMapRendererTest.php +++ b/src/Symfony/Component/AssetMapper/Tests/ImportMap/ImportMapRendererTest.php @@ -15,6 +15,9 @@ use Symfony\Component\Asset\Packages; use Symfony\Component\AssetMapper\ImportMap\ImportMapManager; use Symfony\Component\AssetMapper\ImportMap\ImportMapRenderer; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\RequestStack; +use Symfony\Component\WebLink\GenericLinkProvider; class ImportMapRendererTest extends TestCase { @@ -130,4 +133,40 @@ private function createBasicImportMapManager(): ImportMapManager return $importMapManager; } + + public function testItAddsPreloadLinks() + { + $importMapManager = $this->createMock(ImportMapManager::class); + $importMapManager->expects($this->once()) + ->method('getImportMapData') + ->willReturn([ + 'app_js_preload' => [ + 'path' => '/assets/app-preload-d1g35t.js', + 'type' => 'js', + 'preload' => true, + ], + 'app_css_preload' => [ + 'path' => '/assets/styles/app-preload-d1g35t.css', + 'type' => 'css', + 'preload' => true, + ], + 'app_css_no_preload' => [ + 'path' => '/assets/styles/app-nopreload-d1g35t.css', + 'type' => 'css', + ], + ]); + + $request = Request::create('/foo'); + $requestStack = new RequestStack(); + $requestStack->push($request); + + $renderer = new ImportMapRenderer($importMapManager, requestStack: $requestStack); + $renderer->render(['app']); + + $linkProvider = $request->attributes->get('_links'); + $this->assertInstanceOf(GenericLinkProvider::class, $linkProvider); + $this->assertCount(1, $linkProvider->getLinks()); + $this->assertSame(['preload'], $linkProvider->getLinks()[0]->getRels()); + $this->assertSame('/assets/styles/app-preload-d1g35t.css', $linkProvider->getLinks()[0]->getHref()); + } } diff --git a/src/Symfony/Component/AssetMapper/composer.json b/src/Symfony/Component/AssetMapper/composer.json index 33b0a2e89367d..3ff5377fbdac8 100644 --- a/src/Symfony/Component/AssetMapper/composer.json +++ b/src/Symfony/Component/AssetMapper/composer.json @@ -29,7 +29,8 @@ "symfony/finder": "^5.4|^6.0|^7.0", "symfony/framework-bundle": "^6.4|^7.0", "symfony/http-foundation": "^5.4|^6.0|^7.0", - "symfony/http-kernel": "^5.4|^6.0|^7.0" + "symfony/http-kernel": "^5.4|^6.0|^7.0", + "symfony/web-link": "^5.4|^6.0|^7.0" }, "conflict": { "symfony/framework-bundle": "<6.4" pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy