Skip to content

Commit

Permalink
[AssetMapper] Fix wiring resolvers, send requests in parallel and rew…
Browse files Browse the repository at this point in the history
…rite AssetMapper
  • Loading branch information
nicolas-grekas committed May 24, 2023
1 parent de44614 commit f624325
Show file tree
Hide file tree
Showing 34 changed files with 484 additions and 550 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ class UnusedTagsPass implements CompilerPassInterface
'annotations.cached_reader',
'assets.package',
'asset_mapper.compiler',
'asset_mapper.importmap.resolver',
'auto_alias',
'cache.pool',
'cache.pool.clearer',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -902,7 +902,7 @@ private function addAssetMapperSection(ArrayNodeDefinition $rootNode, callable $
->defaultValue('%kernel.project_dir%/assets/vendor')
->end()
->scalarNode('provider')
->info('The provider (CDN) to use'.class_exists(ImportMapManager::class) ? sprintf(' (e.g.: "%s").', implode('", "', ImportMapManager::PROVIDERS)) : '.')
->info('The provider (CDN) to use'.(class_exists(ImportMapManager::class) ? sprintf(' (e.g.: "%s").', implode('", "', ImportMapManager::PROVIDERS)) : '.'))
->defaultValue('jsdelivr.esm')
->end()
->end()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
use Symfony\Component\AssetMapper\AssetMapper;
use Symfony\Component\AssetMapper\Compiler\AssetCompilerInterface;
use Symfony\Component\AssetMapper\ImportMap\ImportMapManager;
use Symfony\Component\AssetMapper\ImportMap\Resolver\PackageResolverInterface;
use Symfony\Component\BrowserKit\AbstractBrowser;
use Symfony\Component\Cache\Adapter\AdapterInterface;
use Symfony\Component\Cache\Adapter\ArrayAdapter;
Expand Down Expand Up @@ -1316,14 +1317,8 @@ private function registerAssetMapperConfiguration(array $config, ContainerBuilde
->replaceArgument(3, $config['vendor_dir'])
;

$importMapProviderId = 'asset_mapper.importmap.provider.jspm_provider';
if (ImportMapManager::PROVIDER_JSDELIVR_ESM === $config['provider']) {
$importMapProviderId = 'asset_mapper.importmap.provider.js_delivr_esm_provider';
}
$container->setAlias('asset_mapper.importmap.provider', new Alias($importMapProviderId));

$container
->getDefinition('asset_mapper.importmap.provider.jspm_provider')
->getDefinition('asset_mapper.importmap.resolver')
->replaceArgument(0, $config['provider'])
;

Expand All @@ -1332,6 +1327,9 @@ private function registerAssetMapperConfiguration(array $config, ContainerBuilde
->replaceArgument(2, $config['importmap_polyfill'] ?? ImportMapManager::POLYFILL_URL)
->replaceArgument(3, $config['importmap_script_attributes'])
;

$container->registerForAutoconfiguration(PackageResolverInterface::class)
->addTag('asset_mapper.importmap.resolver');
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,9 @@
use Symfony\Component\AssetMapper\Factory\MappedAssetFactory;
use Symfony\Component\AssetMapper\ImportMap\ImportMapManager;
use Symfony\Component\AssetMapper\ImportMap\ImportMapRenderer;
use Symfony\Component\AssetMapper\ImportMap\Providers\JsDelivrEsmImportMapProvider;
use Symfony\Component\AssetMapper\ImportMap\Providers\JspmImportMapProvider;
use Symfony\Component\AssetMapper\ImportMap\Resolver\JsDelivrEsmResolver;
use Symfony\Component\AssetMapper\ImportMap\Resolver\JspmResolver;
use Symfony\Component\AssetMapper\ImportMap\Resolver\PackageResolver;
use Symfony\Component\AssetMapper\MapperAwareAssetPackage;
use Symfony\Component\AssetMapper\Path\PublicAssetsPathResolver;
use Symfony\Component\HttpKernel\Event\RequestEvent;
Expand Down Expand Up @@ -138,17 +139,39 @@
service('asset_mapper.public_assets_path_resolver'),
abstract_arg('importmap.php path'),
abstract_arg('vendor directory'),
// dynamic alias to the chosen provider
service('asset_mapper.importmap.provider'),
service('asset_mapper.importmap.resolver'),
])
->alias(ImportMapManager::class, 'asset_mapper.importmap.manager')

->set('asset_mapper.importmap.provider.jspm_provider', JspmImportMapProvider::class)
->set('asset_mapper.importmap.resolver', PackageResolver::class)
->args([
abstract_arg('provider'),
tagged_locator('asset_mapper.importmap.resolver'),
])

->set('asset_mapper.importmap.provider.js_delivr_esm_provider', JsDelivrEsmImportMapProvider::class)
->set('asset_mapper.importmap.resolver.jsdelivr_esm', JsDelivrEsmResolver::class)
->args([service('http_client')])
->tag('asset_mapper.importmap.resolver', ['resolver' => ImportMapManager::PROVIDER_JSDELIVR_ESM])

->set('asset_mapper.importmap.resolver.jspm', JspmResolver::class)
->args([service('http_client'), ImportMapManager::PROVIDER_JSPM])
->tag('asset_mapper.importmap.resolver', ['resolver' => ImportMapManager::PROVIDER_JSPM])

->set('asset_mapper.importmap.resolver.jspm_system', JspmResolver::class)
->args([service('http_client'), ImportMapManager::PROVIDER_JSPM_SYSTEM])
->tag('asset_mapper.importmap.resolver', ['resolver' => ImportMapManager::PROVIDER_JSPM_SYSTEM])

->set('asset_mapper.importmap.resolver.skypack', JspmResolver::class)
->args([service('http_client'), ImportMapManager::PROVIDER_SKYPACK])
->tag('asset_mapper.importmap.resolver', ['resolver' => ImportMapManager::PROVIDER_SKYPACK])

->set('asset_mapper.importmap.resolver.jsdelivr', JspmResolver::class)
->args([service('http_client'), ImportMapManager::PROVIDER_JSDELIVR])
->tag('asset_mapper.importmap.resolver', ['resolver' => ImportMapManager::PROVIDER_JSDELIVR])

->set('asset_mapper.importmap.resolver.unpkg', JspmResolver::class)
->args([service('http_client'), ImportMapManager::PROVIDER_UNPKG])
->tag('asset_mapper.importmap.resolver', ['resolver' => ImportMapManager::PROVIDER_UNPKG])

->set('asset_mapper.importmap.renderer', ImportMapRenderer::class)
->args([
Expand Down
2 changes: 1 addition & 1 deletion src/Symfony/Component/AssetMapper/AssetMapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ public function getPublicPath(string $logicalPath): ?string

$asset = $this->getAsset($logicalPath);

return $asset?->getPublicPath();
return $asset?->publicPath;
}

private function loadManifest(): array
Expand Down
6 changes: 3 additions & 3 deletions src/Symfony/Component/AssetMapper/AssetMapperCompiler.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,14 @@ public function __construct(private readonly iterable $assetCompilers, private r
{
}

public function compile(string $content, MappedAsset $mappedAsset): string
public function compile(string $content, MappedAsset $asset): string
{
foreach ($this->assetCompilers as $compiler) {
if (!$compiler->supports($mappedAsset)) {
if (!$compiler->supports($asset)) {
continue;
}

$content = $compiler->compile($content, $mappedAsset, $this->assetMapper ??= ($this->assetMapperFactory)());
$content = $compiler->compile($content, $asset, $this->assetMapper ??= ($this->assetMapperFactory)());
}

return $content;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,15 +128,15 @@ public function onKernelRequest(RequestEvent $event): void
throw new NotFoundHttpException(sprintf('Asset with public path "%s" not found.', $pathInfo));
}

$mediaType = $this->getMediaType($asset->getPublicPath());
$mediaType = $this->getMediaType($asset->publicPath);
$response = (new Response(
$asset->getContent(),
$asset->content,
headers: $mediaType ? ['Content-Type' => $mediaType] : [],
))
->setPublic()
->setMaxAge(604800)
->setImmutable()
->setEtag($asset->getDigest())
->setEtag($asset->digest)
;

$event->setResponse($response);
Expand Down Expand Up @@ -164,15 +164,15 @@ private function findAssetFromCache(string $pathInfo): ?MappedAsset
$cachedAsset = $this->cacheMapCache->getItem(hash('xxh128', $pathInfo));
$asset = $cachedAsset->isHit() ? $this->assetMapper->getAsset($cachedAsset->get()) : null;

if (null !== $asset && $asset->getPublicPath() === $pathInfo) {
if (null !== $asset && $asset->publicPath === $pathInfo) {
return $asset;
}
}

// we did not find a match
$asset = null;
foreach ($this->assetMapper->allAssets() as $assetCandidate) {
if ($pathInfo === $assetCandidate->getPublicPath()) {
if ($pathInfo === $assetCandidate->publicPath) {
$asset = $assetCandidate;
break;
}
Expand All @@ -183,7 +183,7 @@ private function findAssetFromCache(string $pathInfo): ?MappedAsset
}

if (null !== $cachedAsset) {
$cachedAsset->set($asset->getLogicalPath());
$cachedAsset->set($asset->logicalPath);
$this->cacheMapCache->save($cachedAsset);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,14 +122,14 @@ private function createManifestAndWriteFiles(SymfonyStyle $io, string $publicDir
$manifest = [];
foreach ($allAssets as $asset) {
// $asset->getPublicPath() will start with a "/"
$targetPath = $publicDir.$asset->getPublicPath();
$targetPath = $publicDir.$asset->publicPath;

if (!is_dir($dir = \dirname($targetPath))) {
$this->filesystem->mkdir($dir);
}

$this->filesystem->dumpFile($targetPath, $asset->getContent());
$manifest[$asset->getLogicalPath()] = $asset->getPublicPath();
$this->filesystem->dumpFile($targetPath, $asset->content);
$manifest[$asset->logicalPath] = $asset->publicPath;
}
ksort($manifest);
$io->comment(sprintf('Compiled <info>%d</info> assets', \count($manifest)));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,8 @@ protected function execute(InputInterface $input, OutputInterface $output): int

$rows = [];
foreach ($allAssets as $asset) {
$logicalPath = $asset->getLogicalPath();
$sourcePath = $this->relativizePath($asset->getSourcePath());
$logicalPath = $asset->logicalPath;
$sourcePath = $this->relativizePath($asset->sourcePath);

if (!$input->getOption('full')) {
$logicalPath = $this->shortenPath($logicalPath);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,31 +45,31 @@ public function compile(string $content, MappedAsset $asset, AssetMapperInterfac
{
return preg_replace_callback(self::ASSET_URL_PATTERN, function ($matches) use ($asset, $assetMapper) {
try {
$resolvedPath = $this->resolvePath(\dirname($asset->getLogicalPath()), $matches[1]);
$resolvedPath = $this->resolvePath(\dirname($asset->logicalPath), $matches[1]);
} catch (RuntimeException $e) {
$this->handleMissingImport(sprintf('Error processing import in "%s": "%s"', $asset->getSourcePath(), $e->getMessage()), $e);
$this->handleMissingImport(sprintf('Error processing import in "%s": ', $asset->sourcePath).$e->getMessage(), $e);

return $matches[0];
}
$dependentAsset = $assetMapper->getAsset($resolvedPath);

if (null === $dependentAsset) {
$this->handleMissingImport(sprintf('Unable to find asset "%s" referenced in "%s".', $matches[1], $asset->getSourcePath()));
$this->handleMissingImport(sprintf('Unable to find asset "%s" referenced in "%s".', $matches[1], $asset->sourcePath));

// return original, unchanged path
return $matches[0];
}

$asset->addDependency(new AssetDependency($dependentAsset));
$relativePath = $this->createRelativePath($asset->getPublicPathWithoutDigest(), $dependentAsset->getPublicPath());
$relativePath = $this->createRelativePath($asset->publicPathWithoutDigest, $dependentAsset->publicPath);

return 'url("'.$relativePath.'")';
}, $content);
}

public function supports(MappedAsset $asset): bool
{
return 'css' === $asset->getPublicExtension();
return 'css' === $asset->publicExtension;
}

private function handleMissingImport(string $message, \Throwable $e = null): void
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,17 +45,17 @@ public function compile(string $content, MappedAsset $asset, AssetMapperInterfac
{
return preg_replace_callback(self::IMPORT_PATTERN, function ($matches) use ($asset, $assetMapper) {
try {
$resolvedPath = $this->resolvePath(\dirname($asset->getLogicalPath()), $matches[1]);
$resolvedPath = $this->resolvePath(\dirname($asset->logicalPath), $matches[1]);
} catch (RuntimeException $e) {
$this->handleMissingImport(sprintf('Error processing import in "%s": "%s"', $asset->getSourcePath(), $e->getMessage()), $e);
$this->handleMissingImport(sprintf('Error processing import in "%s": ', $asset->sourcePath).$e->getMessage(), $e);

return $matches[0];
}

$dependentAsset = $assetMapper->getAsset($resolvedPath);

if (!$dependentAsset) {
$message = sprintf('Unable to find asset "%s" imported from "%s".', $matches[1], $asset->getSourcePath());
$message = sprintf('Unable to find asset "%s" imported from "%s".', $matches[1], $asset->sourcePath);

if (null !== $assetMapper->getAsset(sprintf('%s.js', $resolvedPath))) {
$message .= sprintf(' Try adding ".js" to the end of the import - i.e. "%s.js".', $matches[1]);
Expand All @@ -73,7 +73,7 @@ public function compile(string $content, MappedAsset $asset, AssetMapperInterfac

$asset->addDependency(new AssetDependency($dependentAsset, $isLazy, false));

$relativeImportPath = $this->createRelativePath($asset->getPublicPathWithoutDigest(), $dependentAsset->getPublicPathWithoutDigest());
$relativeImportPath = $this->createRelativePath($asset->publicPathWithoutDigest, $dependentAsset->publicPathWithoutDigest);
$relativeImportPath = $this->makeRelativeForJavaScript($relativeImportPath);

return str_replace($matches[1], $relativeImportPath, $matches[0]);
Expand All @@ -85,7 +85,7 @@ public function compile(string $content, MappedAsset $asset, AssetMapperInterfac

public function supports(MappedAsset $asset): bool
{
return 'js' === $asset->getPublicExtension();
return 'js' === $asset->publicExtension;
}

private function makeRelativeForJavaScript(string $path): string
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,13 @@ final class SourceMappingUrlsCompiler implements AssetCompilerInterface

public function supports(MappedAsset $asset): bool
{
return \in_array($asset->getPublicExtension(), ['css', 'js'], true);
return \in_array($asset->publicExtension, ['css', 'js'], true);
}

public function compile(string $content, MappedAsset $asset, AssetMapperInterface $assetMapper): string
{
return preg_replace_callback(self::SOURCE_MAPPING_PATTERN, function ($matches) use ($asset, $assetMapper) {
$resolvedPath = $this->resolvePath(\dirname($asset->getLogicalPath()), $matches[2]);
$resolvedPath = $this->resolvePath(\dirname($asset->logicalPath), $matches[2]);

$dependentAsset = $assetMapper->getAsset($resolvedPath);
if (!$dependentAsset) {
Expand All @@ -45,7 +45,7 @@ public function compile(string $content, MappedAsset $asset, AssetMapperInterfac
}

$asset->addDependency(new AssetDependency($dependentAsset));
$relativePath = $this->createRelativePath($asset->getPublicPathWithoutDigest(), $dependentAsset->getPublicPath());
$relativePath = $this->createRelativePath($asset->publicPathWithoutDigest, $dependentAsset->publicPath);

return $matches[1].'# sourceMappingURL='.$relativePath;
}, $content);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ private function getCacheFilePath(string $logicalPath, string $sourcePath): stri
private function collectResourcesFromAsset(MappedAsset $mappedAsset): array
{
$resources = array_map(fn (string $path) => new FileResource($path), $mappedAsset->getFileDependencies());
$resources[] = new FileResource($mappedAsset->getSourcePath());
$resources[] = new FileResource($mappedAsset->sourcePath);

foreach ($mappedAsset->getDependencies() as $dependency) {
if (!$dependency->isContentDependency) {
Expand Down
Loading

0 comments on commit f624325

Please sign in to comment.