Skip to content

Commit 5587c5c

Browse files
[AssetMapper][FrameworkBundle] Add cache warmer for AssetMapper compilation
1 parent 73d4904 commit 5587c5c

File tree

5 files changed

+184
-2
lines changed

5 files changed

+184
-2
lines changed

src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
CHANGELOG
22
=========
33

4+
7.3
5+
---
6+
7+
* Add cache warmer for AssetMapper compilation
8+
49
7.2
510
---
611

src/Symfony/Bundle/FrameworkBundle/Resources/config/asset_mapper.php

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
use Symfony\Component\AssetMapper\AssetMapperDevServerSubscriber;
1717
use Symfony\Component\AssetMapper\AssetMapperInterface;
1818
use Symfony\Component\AssetMapper\AssetMapperRepository;
19+
use Symfony\Component\AssetMapper\CacheWarmer\AssetMapperCacheWarmer;
1920
use Symfony\Component\AssetMapper\Command\AssetMapperCompileCommand;
2021
use Symfony\Component\AssetMapper\Command\DebugAssetMapperCommand;
2122
use Symfony\Component\AssetMapper\Command\ImportMapAuditCommand;
@@ -253,6 +254,18 @@
253254

254255
->set('asset_mapper.importmap.command.outdated', ImportMapOutdatedCommand::class)
255256
->args([service('asset_mapper.importmap.update_checker')])
256-
->tag('console.command')
257-
;
257+
->tag('console.command');
258+
259+
if (class_exists(AssetMapperCacheWarmer::class)) {
260+
$container->services()
261+
->set('asset_mapper.compile.cache_warmer', AssetMapperCacheWarmer::class)
262+
->args([
263+
service('asset_mapper.compiled_asset_mapper_config_reader'),
264+
service('asset_mapper'),
265+
service('asset_mapper.importmap.generator'),
266+
service('asset_mapper.local_public_assets_filesystem'),
267+
service('event_dispatcher')->nullOnInvalid(),
268+
])
269+
->tag('kernel.cache_warmer');
270+
}
258271
};

src/Symfony/Component/AssetMapper/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
CHANGELOG
22
=========
33

4+
7.3
5+
---
6+
7+
* Add `AssetMapperCacheWarmer`
8+
49
7.2
510
---
611

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\AssetMapper\CacheWarmer;
13+
14+
use Symfony\Component\AssetMapper\AssetMapper;
15+
use Symfony\Component\AssetMapper\AssetMapperInterface;
16+
use Symfony\Component\AssetMapper\CompiledAssetMapperConfigReader;
17+
use Symfony\Component\AssetMapper\Event\PreAssetsCompileEvent;
18+
use Symfony\Component\AssetMapper\ImportMap\ImportMapGenerator;
19+
use Symfony\Component\AssetMapper\Path\PublicAssetsFilesystemInterface;
20+
use Symfony\Component\Console\Output\NullOutput;
21+
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
22+
use Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerInterface;
23+
24+
/**
25+
* @author Ryan Weaver <ryan@symfonycasts.com>
26+
* @author Alexandre Daubois <alex.daubois@gmail.com>
27+
*/
28+
final class AssetMapperCacheWarmer implements CacheWarmerInterface
29+
{
30+
public function __construct(
31+
private readonly CompiledAssetMapperConfigReader $compiledConfigReader,
32+
private readonly AssetMapperInterface $assetMapper,
33+
private readonly ImportMapGenerator $importMapGenerator,
34+
private readonly PublicAssetsFilesystemInterface $assetsFilesystem,
35+
private readonly ?EventDispatcherInterface $eventDispatcher = null,
36+
) {
37+
}
38+
39+
public function isOptional(): bool
40+
{
41+
return false;
42+
}
43+
44+
public function warmUp(string $cacheDir, ?string $buildDir = null): array
45+
{
46+
$this->compiledConfigReader->removeConfig(AssetMapper::MANIFEST_FILE_NAME);
47+
$this->compiledConfigReader->removeConfig(ImportMapGenerator::IMPORT_MAP_CACHE_FILENAME);
48+
49+
$entrypointFiles = [];
50+
foreach ($this->importMapGenerator->getEntrypointNames() as $entrypointName) {
51+
$path = \sprintf(ImportMapGenerator::ENTRYPOINT_CACHE_FILENAME_PATTERN, $entrypointName);
52+
$this->compiledConfigReader->removeConfig($path);
53+
$entrypointFiles[$entrypointName] = $path;
54+
}
55+
56+
$this->eventDispatcher?->dispatch(new PreAssetsCompileEvent(new NullOutput()));
57+
58+
$manifest = $this->createManifestAndWriteFiles();
59+
$this->compiledConfigReader->saveConfig(AssetMapper::MANIFEST_FILE_NAME, $manifest);
60+
61+
$this->compiledConfigReader->saveConfig(
62+
ImportMapGenerator::IMPORT_MAP_CACHE_FILENAME,
63+
$this->importMapGenerator->getRawImportMapData()
64+
);
65+
66+
foreach ($entrypointFiles as $entrypointName => $path) {
67+
$this->compiledConfigReader->saveConfig(
68+
$path,
69+
$this->importMapGenerator->findEagerEntrypointImports($entrypointName)
70+
);
71+
}
72+
73+
return [];
74+
}
75+
76+
private function createManifestAndWriteFiles(): array
77+
{
78+
$manifest = [];
79+
foreach ($this->assetMapper->allAssets() as $asset) {
80+
if (null !== $asset->content) {
81+
$this->assetsFilesystem->write($asset->publicPath, $asset->content);
82+
} else {
83+
$this->assetsFilesystem->copy($asset->sourcePath, $asset->publicPath);
84+
}
85+
86+
$manifest[$asset->logicalPath] = $asset->publicPath;
87+
}
88+
ksort($manifest);
89+
90+
return $manifest;
91+
}
92+
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\AssetMapper\Tests\CacheWarmer;
13+
14+
use PHPUnit\Framework\TestCase;
15+
use Symfony\Component\AssetMapper\AssetMapper;
16+
use Symfony\Component\AssetMapper\AssetMapperInterface;
17+
use Symfony\Component\AssetMapper\CacheWarmer\AssetMapperCacheWarmer;
18+
use Symfony\Component\AssetMapper\CompiledAssetMapperConfigReader;
19+
use Symfony\Component\AssetMapper\Event\PreAssetsCompileEvent;
20+
use Symfony\Component\AssetMapper\ImportMap\ImportMapGenerator;
21+
use Symfony\Component\AssetMapper\Path\PublicAssetsFilesystemInterface;
22+
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
23+
24+
class AssetMapperCacheWarmerTest extends TestCase
25+
{
26+
public function testWarmUpCleansAndWrites()
27+
{
28+
$cacheDir = sys_get_temp_dir();
29+
30+
$importMapGenerator = $this->createMock(ImportMapGenerator::class);
31+
$importMapGenerator->expects($this->once())
32+
->method('getEntrypointNames')
33+
->willReturn(['entrypoint1', 'entrypoint2']);
34+
35+
$eventDispatcher = $this->createMock(EventDispatcherInterface::class);
36+
$eventDispatcher->expects($this->once())
37+
->method('dispatch')
38+
->with($this->isInstanceOf(PreAssetsCompileEvent::class));
39+
40+
$warmer = new AssetMapperCacheWarmer(
41+
new CompiledAssetMapperConfigReader($cacheDir),
42+
$this->createMock(AssetMapperInterface::class),
43+
$importMapGenerator,
44+
$this->createMock(PublicAssetsFilesystemInterface::class),
45+
$eventDispatcher,
46+
);
47+
48+
$this->assertFileDoesNotExist($cacheDir.'/'.AssetMapper::MANIFEST_FILE_NAME);
49+
$this->assertFileDoesNotExist($cacheDir.'/'.ImportMapGenerator::IMPORT_MAP_CACHE_FILENAME);
50+
$this->assertFileDoesNotExist($cacheDir.'/entrypoint.entrypoint1.json');
51+
$this->assertFileDoesNotExist($cacheDir.'/entrypoint.entrypoint2.json');
52+
53+
try {
54+
$this->assertEmpty($warmer->warmUp($cacheDir));
55+
56+
$this->assertFileExists($cacheDir.'/'.AssetMapper::MANIFEST_FILE_NAME);
57+
$this->assertFileExists($cacheDir.'/'.ImportMapGenerator::IMPORT_MAP_CACHE_FILENAME);
58+
$this->assertFileExists($cacheDir.'/entrypoint.entrypoint1.json');
59+
$this->assertFileExists($cacheDir.'/entrypoint.entrypoint2.json');
60+
} finally {
61+
@unlink($cacheDir.'/'.AssetMapper::MANIFEST_FILE_NAME);
62+
@unlink($cacheDir.'/'.ImportMapGenerator::IMPORT_MAP_CACHE_FILENAME);
63+
@unlink($cacheDir.'/entrypoint.entrypoint1.json');
64+
@unlink($cacheDir.'/entrypoint.entrypoint2.json');
65+
}
66+
}
67+
}

0 commit comments

Comments
 (0)