From 4b6294e277280639aea595d265d1ee2c0f070593 Mon Sep 17 00:00:00 2001 From: Florent Morselli Date: Fri, 8 Mar 2024 20:08:59 +0100 Subject: [PATCH] HasCacheStrategies interface --- src/Resources/config/services.php | 6 +-- src/Service/CacheStrategy.php | 53 +++++++++++++++++++++++++++ src/Service/HasCacheStrategies.php | 13 +++++++ src/Service/Rule/AssetCache.php | 37 ++++++++++++++++--- src/Service/Rule/BackgroundSync.php | 42 +++++++++++++++++++-- src/Service/Rule/ClearCache.php | 18 +++++++-- src/Service/Rule/FontCache.php | 41 +++++++++++++++++---- src/Service/Rule/GoogleFontCache.php | 35 +++++++++++++++--- src/Service/Rule/ImageCache.php | 42 ++++++++++++++++++--- src/Service/Rule/ManifestCache.php | 29 +++++++++++++-- src/Service/Rule/OfflineFallback.php | 20 +++++++--- src/Service/Rule/PageCache.php | 38 ++++++++++++++++--- src/Service/Rule/WorkboxImport.php | 22 ++++++++--- src/Service/Rule/WorkboxRule.php | 12 ------ src/Service/ServiceWorkerCompiler.php | 10 ----- 15 files changed, 342 insertions(+), 76 deletions(-) create mode 100644 src/Service/CacheStrategy.php create mode 100644 src/Service/HasCacheStrategies.php delete mode 100644 src/Service/Rule/WorkboxRule.php diff --git a/src/Resources/config/services.php b/src/Resources/config/services.php index d95560c..479e039 100644 --- a/src/Resources/config/services.php +++ b/src/Resources/config/services.php @@ -9,9 +9,9 @@ use SpomkyLabs\PwaBundle\Dto\ServiceWorker; use SpomkyLabs\PwaBundle\ImageProcessor\GDImageProcessor; use SpomkyLabs\PwaBundle\ImageProcessor\ImagickImageProcessor; +use SpomkyLabs\PwaBundle\Service\CacheStrategy; use SpomkyLabs\PwaBundle\Service\ManifestBuilder; use SpomkyLabs\PwaBundle\Service\Rule\ServiceWorkerRule; -use SpomkyLabs\PwaBundle\Service\Rule\WorkboxRule; use SpomkyLabs\PwaBundle\Service\ServiceWorkerBuilder; use SpomkyLabs\PwaBundle\Service\ServiceWorkerCompiler; use SpomkyLabs\PwaBundle\Subscriber\ManifestCompileEventListener; @@ -110,8 +110,8 @@ $container->instanceof(ServiceWorkerRule::class) ->tag('spomky_labs_pwa.service_worker_rule') ; - $container->instanceof(WorkboxRule::class) - ->tag('spomky_labs_pwa.workbox_rule') + $container->instanceof(CacheStrategy::class) + ->tag('spomky_labs_pwa.cache_strategy') ; $container->load('SpomkyLabs\\PwaBundle\\Service\\Rule\\', '../../Service/Rule/*'); }; diff --git a/src/Service/CacheStrategy.php b/src/Service/CacheStrategy.php new file mode 100644 index 0000000..294abf1 --- /dev/null +++ b/src/Service/CacheStrategy.php @@ -0,0 +1,53 @@ + + */ + public function getCacheStrategies(): array; +} diff --git a/src/Service/Rule/AssetCache.php b/src/Service/Rule/AssetCache.php index c554ac1..aa97f0c 100644 --- a/src/Service/Rule/AssetCache.php +++ b/src/Service/Rule/AssetCache.php @@ -4,7 +4,10 @@ namespace SpomkyLabs\PwaBundle\Service\Rule; +use SpomkyLabs\PwaBundle\Dto\ServiceWorker; use SpomkyLabs\PwaBundle\Dto\Workbox; +use SpomkyLabs\PwaBundle\Service\CacheStrategy; +use SpomkyLabs\PwaBundle\Service\HasCacheStrategies; use Symfony\Component\AssetMapper\AssetMapperInterface; use Symfony\Component\AssetMapper\Path\PublicAssetsPathResolverInterface; use Symfony\Component\DependencyInjection\Attribute\Autowire; @@ -18,7 +21,7 @@ use const JSON_UNESCAPED_UNICODE; use const PHP_EOL; -final readonly class AssetCache implements WorkboxRule +final readonly class AssetCache implements ServiceWorkerRule, HasCacheStrategies { /** * @var array @@ -27,7 +30,10 @@ private string $assetPublicPrefix; + private Workbox $workbox; + public function __construct( + ServiceWorker $serviceWorker, #[Autowire(service: 'asset_mapper.public_assets_path_resolver')] PublicAssetsPathResolverInterface $publicAssetsPathResolver, private AssetMapperInterface $assetMapper, @@ -35,6 +41,7 @@ public function __construct( #[Autowire('%kernel.debug%')] bool $debug, ) { + $this->workbox = $serviceWorker->workbox; $this->assetPublicPrefix = rtrim($publicAssetsPathResolver->resolvePublicPath(''), '/'); $options = [ AbstractObjectNormalizer::SKIP_UNINITIALIZED_VALUES => true, @@ -47,14 +54,17 @@ public function __construct( $this->jsonOptions = $options; } - public function process(Workbox $workbox, string $body): string + public function process(string $body): string { - if ($workbox->assetCache->enabled === false) { + if ($this->workbox->enabled === false) { + return $body; + } + if ($this->workbox->assetCache->enabled === false) { return $body; } $assets = []; foreach ($this->assetMapper->allAssets() as $asset) { - if (preg_match($workbox->assetCache->regex, $asset->sourcePath) === 1) { + if (preg_match($this->workbox->assetCache->regex, $asset->sourcePath) === 1) { $assets[] = $asset->publicPath; } } @@ -63,7 +73,7 @@ public function process(Workbox $workbox, string $body): string $declaration = <<assetCache->cacheName}', + cacheName: '{$this->workbox->assetCache->cacheName}', plugins: [ new workbox.cacheableResponse.CacheableResponsePlugin({statuses: [0, 200]}), new workbox.expiration.ExpirationPlugin({ @@ -91,4 +101,21 @@ public function process(Workbox $workbox, string $body): string return $body . PHP_EOL . PHP_EOL . trim($declaration); } + + public function getCacheStrategies(): array + { + return [ + CacheStrategy::create( + $this->workbox->assetCache->cacheName, + CacheStrategy::STRATEGY_CACHE_FIRST, + sprintf("'({url}) => url.pathname.startsWith('%s')'", $this->assetPublicPrefix), + $this->workbox->enabled && $this->workbox->assetCache->enabled, + true, + [ + 'maxEntries' => -1, + 'maxAge' => 365 * 24 * 60 * 60, + ], + ), + ]; + } } diff --git a/src/Service/Rule/BackgroundSync.php b/src/Service/Rule/BackgroundSync.php index 448ef63..8a1155d 100644 --- a/src/Service/Rule/BackgroundSync.php +++ b/src/Service/Rule/BackgroundSync.php @@ -4,19 +4,32 @@ namespace SpomkyLabs\PwaBundle\Service\Rule; +use SpomkyLabs\PwaBundle\Dto\ServiceWorker; use SpomkyLabs\PwaBundle\Dto\Workbox; +use SpomkyLabs\PwaBundle\Service\CacheStrategy; +use SpomkyLabs\PwaBundle\Service\HasCacheStrategies; use const PHP_EOL; -final readonly class BackgroundSync implements WorkboxRule +final readonly class BackgroundSync implements ServiceWorkerRule, HasCacheStrategies { - public function process(Workbox $workbox, string $body): string + private Workbox $workbox; + + public function __construct(ServiceWorker $serviceWorker) + { + $this->workbox = $serviceWorker->workbox; + } + + public function process(string $body): string { - if ($workbox->backgroundSync === []) { + if ($this->workbox->enabled === false) { + return $body; + } + if ($this->workbox->backgroundSync === []) { return $body; } $declaration = ''; - foreach ($workbox->backgroundSync as $sync) { + foreach ($this->workbox->backgroundSync as $sync) { $forceSyncFallback = $sync->forceSyncFallback === true ? 'true' : 'false'; $broadcastChannel = ''; if ($sync->broadcastChannel !== null) { @@ -50,4 +63,25 @@ public function process(Workbox $workbox, string $body): string return $body . PHP_EOL . PHP_EOL . trim($declaration); } + + public function getCacheStrategies(): array + { + $strategies = []; + foreach ($this->workbox->backgroundSync as $sync) { + $strategies[] = CacheStrategy::create( + 'backgroundSync', + CacheStrategy::STRATEGY_NETWORK_ONLY, + $sync->regex, + $this->workbox->enabled, + true, + [ + 'maxTimeout' => 0, + 'maxAge' => 0, + 'maxEntries' => 0, + ] + ); + } + + return $strategies; + } } diff --git a/src/Service/Rule/ClearCache.php b/src/Service/Rule/ClearCache.php index 94c8635..d41f25e 100644 --- a/src/Service/Rule/ClearCache.php +++ b/src/Service/Rule/ClearCache.php @@ -4,14 +4,26 @@ namespace SpomkyLabs\PwaBundle\Service\Rule; +use SpomkyLabs\PwaBundle\Dto\ServiceWorker; use SpomkyLabs\PwaBundle\Dto\Workbox; use const PHP_EOL; -final readonly class ClearCache implements WorkboxRule +final readonly class ClearCache implements ServiceWorkerRule { - public function process(Workbox $workbox, string $body): string + private Workbox $workbox; + + public function __construct( + ServiceWorker $serviceWorker + ) { + $this->workbox = $serviceWorker->workbox; + } + + public function process(string $body): string { - if ($workbox->clearCache === false) { + if ($this->workbox->enabled === false) { + return $body; + } + if ($this->workbox->clearCache === false) { return $body; } diff --git a/src/Service/Rule/FontCache.php b/src/Service/Rule/FontCache.php index 2cb4a9a..771349a 100644 --- a/src/Service/Rule/FontCache.php +++ b/src/Service/Rule/FontCache.php @@ -4,7 +4,10 @@ namespace SpomkyLabs\PwaBundle\Service\Rule; +use SpomkyLabs\PwaBundle\Dto\ServiceWorker; use SpomkyLabs\PwaBundle\Dto\Workbox; +use SpomkyLabs\PwaBundle\Service\CacheStrategy; +use SpomkyLabs\PwaBundle\Service\HasCacheStrategies; use Symfony\Component\AssetMapper\AssetMapperInterface; use Symfony\Component\DependencyInjection\Attribute\Autowire; use Symfony\Component\Serializer\Encoder\JsonEncode; @@ -16,19 +19,23 @@ use const JSON_UNESCAPED_UNICODE; use const PHP_EOL; -final readonly class FontCache implements WorkboxRule +final readonly class FontCache implements ServiceWorkerRule, HasCacheStrategies { /** * @var array */ private array $jsonOptions; + private Workbox $workbox; + public function __construct( + ServiceWorker $serviceWorker, private AssetMapperInterface $assetMapper, private SerializerInterface $serializer, #[Autowire('%kernel.debug%')] bool $debug, ) { + $this->workbox = $serviceWorker->workbox; $options = [ AbstractObjectNormalizer::SKIP_UNINITIALIZED_VALUES => true, AbstractObjectNormalizer::SKIP_NULL_VALUES => true, @@ -40,14 +47,17 @@ public function __construct( $this->jsonOptions = $options; } - public function process(Workbox $workbox, string $body): string + public function process(string $body): string { - if ($workbox->fontCache->enabled === false) { + if ($this->workbox->enabled === false) { + return $body; + } + if ($this->workbox->fontCache->enabled === false) { return $body; } $fonts = []; foreach ($this->assetMapper->allAssets() as $asset) { - if (preg_match($workbox->fontCache->regex, $asset->sourcePath) === 1) { + if (preg_match($this->workbox->fontCache->regex, $asset->sourcePath) === 1) { $fonts[] = $asset->publicPath; } } @@ -55,14 +65,14 @@ public function process(Workbox $workbox, string $body): string $declaration = <<fontCache->cacheName}', + cacheName: '{$this->workbox->fontCache->cacheName}', plugins: [ new workbox.cacheableResponse.CacheableResponsePlugin({ statuses: [0, 200], }), new workbox.expiration.ExpirationPlugin({ - maxAgeSeconds: {$workbox->fontCache->maxAge}, - maxEntries: {$workbox->fontCache->maxEntries}, + maxAgeSeconds: {$this->workbox->fontCache->maxAge}, + maxEntries: {$this->workbox->fontCache->maxEntries}, }), ], }); @@ -85,4 +95,21 @@ public function process(Workbox $workbox, string $body): string return $body . PHP_EOL . PHP_EOL . trim($declaration); } + + public function getCacheStrategies(): array + { + return [ + CacheStrategy::create( + $this->workbox->fontCache->cacheName, + CacheStrategy::STRATEGY_CACHE_FIRST, + "'({request}) => request.destination === 'font'", + $this->workbox->enabled && $this->workbox->fontCache->enabled, + true, + [ + 'maxEntries' => $this->workbox->fontCache->maxEntries, + 'maxAge' => $this->workbox->fontCache->maxAge, + ], + ), + ]; + } } diff --git a/src/Service/Rule/GoogleFontCache.php b/src/Service/Rule/GoogleFontCache.php index 223eb41..12a0ed8 100644 --- a/src/Service/Rule/GoogleFontCache.php +++ b/src/Service/Rule/GoogleFontCache.php @@ -4,7 +4,10 @@ namespace SpomkyLabs\PwaBundle\Service\Rule; +use SpomkyLabs\PwaBundle\Dto\ServiceWorker; use SpomkyLabs\PwaBundle\Dto\Workbox; +use SpomkyLabs\PwaBundle\Service\CacheStrategy; +use SpomkyLabs\PwaBundle\Service\HasCacheStrategies; use Symfony\Component\DependencyInjection\Attribute\Autowire; use Symfony\Component\Serializer\Encoder\JsonEncode; use Symfony\Component\Serializer\Normalizer\AbstractObjectNormalizer; @@ -16,18 +19,22 @@ use const JSON_UNESCAPED_UNICODE; use const PHP_EOL; -final readonly class GoogleFontCache implements WorkboxRule +final readonly class GoogleFontCache implements ServiceWorkerRule, HasCacheStrategies { /** * @var array */ private array $jsonOptions; + private Workbox $workbox; + public function __construct( + ServiceWorker $serviceWorker, private SerializerInterface $serializer, #[Autowire('%kernel.debug%')] bool $debug, ) { + $this->workbox = $serviceWorker->workbox; $options = [ AbstractObjectNormalizer::SKIP_UNINITIALIZED_VALUES => true, AbstractObjectNormalizer::SKIP_NULL_VALUES => true, @@ -39,15 +46,18 @@ public function __construct( $this->jsonOptions = $options; } - public function process(Workbox $workbox, string $body): string + public function process(string $body): string { - if ($workbox->googleFontCache->enabled === false) { + if ($this->workbox->enabled === false) { + return $body; + } + if ($this->workbox->googleFontCache->enabled === false) { return $body; } $options = [ - 'cachePrefix' => $workbox->googleFontCache->cachePrefix, - 'maxAge' => $workbox->googleFontCache->maxAge, - 'maxEntries' => $workbox->googleFontCache->maxEntries, + 'cachePrefix' => $this->workbox->googleFontCache->cachePrefix, + 'maxAge' => $this->workbox->googleFontCache->maxAge, + 'maxEntries' => $this->workbox->googleFontCache->maxEntries, ]; $options = array_filter($options, static fn (mixed $v): bool => ($v !== null && $v !== '')); $options = count($options) === 0 ? '' : $this->serializer->serialize($options, 'json', $this->jsonOptions); @@ -58,4 +68,17 @@ public function process(Workbox $workbox, string $body): string return $body . PHP_EOL . PHP_EOL . trim($declaration); } + + public function getCacheStrategies(): array + { + return [ + CacheStrategy::create( + 'googleFontsCache', + 'workbox.recipes.googleFontsCache', + 'Google Fonts Cache', + $this->workbox->enabled && $this->workbox->googleFontCache->enabled, + $this->workbox->googleFontCache->enabled + ), + ]; + } } diff --git a/src/Service/Rule/ImageCache.php b/src/Service/Rule/ImageCache.php index 80b984b..3182595 100644 --- a/src/Service/Rule/ImageCache.php +++ b/src/Service/Rule/ImageCache.php @@ -4,37 +4,47 @@ namespace SpomkyLabs\PwaBundle\Service\Rule; +use SpomkyLabs\PwaBundle\Dto\ServiceWorker; use SpomkyLabs\PwaBundle\Dto\Workbox; +use SpomkyLabs\PwaBundle\Service\CacheStrategy; +use SpomkyLabs\PwaBundle\Service\HasCacheStrategies; use Symfony\Component\AssetMapper\Path\PublicAssetsPathResolverInterface; use Symfony\Component\DependencyInjection\Attribute\Autowire; use const PHP_EOL; -final readonly class ImageCache implements WorkboxRule +final readonly class ImageCache implements ServiceWorkerRule, HasCacheStrategies { private string $assetPublicPrefix; + private Workbox $workbox; + public function __construct( + ServiceWorker $serviceWorker, #[Autowire(service: 'asset_mapper.public_assets_path_resolver')] PublicAssetsPathResolverInterface $publicAssetsPathResolver, ) { + $this->workbox = $serviceWorker->workbox; $this->assetPublicPrefix = rtrim($publicAssetsPathResolver->resolvePublicPath(''), '/'); } - public function process(Workbox $workbox, string $body): string + public function process(string $body): string { - if ($workbox->imageCache->enabled === false) { + if ($this->workbox->enabled === false) { + return $body; + } + if ($this->workbox->imageCache->enabled === false) { return $body; } $declaration = << (request.destination === 'image' && !url.pathname.startsWith('{$this->assetPublicPrefix}')), new workbox.strategies.CacheFirst({ - cacheName: '{$workbox->imageCache->cacheName}', + cacheName: '{$this->workbox->imageCache->cacheName}', plugins: [ new workbox.cacheableResponse.CacheableResponsePlugin({statuses: [0, 200]}), new workbox.expiration.ExpirationPlugin({ - maxEntries: {$workbox->imageCache->maxEntries}, - maxAgeSeconds: {$workbox->imageCache->maxAge}, + maxEntries: {$this->workbox->imageCache->maxEntries}, + maxAgeSeconds: {$this->workbox->imageCache->maxAge}, }), ], }) @@ -43,4 +53,24 @@ public function process(Workbox $workbox, string $body): string return $body . PHP_EOL . PHP_EOL . trim($declaration); } + + public function getCacheStrategies(): array + { + return [ + CacheStrategy::create( + $this->workbox->imageCache->cacheName, + CacheStrategy::STRATEGY_CACHE_FIRST, + sprintf( + "'({request, url}) => (request.destination === 'image' && !url.pathname.startsWith('%s'))'", + $this->assetPublicPrefix + ), + $this->workbox->enabled && $this->workbox->imageCache->enabled, + true, + [ + 'maxEntries' => $this->workbox->imageCache->maxEntries, + 'maxAge' => $this->workbox->imageCache->maxAge, + ] + ), + ]; + } } diff --git a/src/Service/Rule/ManifestCache.php b/src/Service/Rule/ManifestCache.php index 471a2ef..47de81f 100644 --- a/src/Service/Rule/ManifestCache.php +++ b/src/Service/Rule/ManifestCache.php @@ -4,24 +4,34 @@ namespace SpomkyLabs\PwaBundle\Service\Rule; +use SpomkyLabs\PwaBundle\Dto\ServiceWorker; use SpomkyLabs\PwaBundle\Dto\Workbox; +use SpomkyLabs\PwaBundle\Service\CacheStrategy; +use SpomkyLabs\PwaBundle\Service\HasCacheStrategies; use Symfony\Component\DependencyInjection\Attribute\Autowire; use const PHP_EOL; -final readonly class ManifestCache implements WorkboxRule +final readonly class ManifestCache implements ServiceWorkerRule, HasCacheStrategies { private string $manifestPublicUrl; + private Workbox $workbox; + public function __construct( + ServiceWorker $serviceWorker, #[Autowire('%spomky_labs_pwa.manifest.public_url%')] string $manifestPublicUrl, ) { + $this->workbox = $serviceWorker->workbox; $this->manifestPublicUrl = '/' . trim($manifestPublicUrl, '/'); } - public function process(Workbox $workbox, string $body): string + public function process(string $body): string { - if ($workbox->cacheManifest === false) { + if ($this->workbox->enabled === false) { + return $body; + } + if ($this->workbox->cacheManifest === false) { return $body; } @@ -36,4 +46,17 @@ public function process(Workbox $workbox, string $body): string return $body . PHP_EOL . PHP_EOL . trim($declaration); } + + public function getCacheStrategies(): array + { + return [ + CacheStrategy::create( + 'manifest', + CacheStrategy::STRATEGY_STALE_WHILE_REVALIDATE, + sprintf("({url}) => '%s' === url.pathname", $this->manifestPublicUrl), + $this->workbox->enabled && $this->workbox->cacheManifest, + true + ), + ]; + } } diff --git a/src/Service/Rule/OfflineFallback.php b/src/Service/Rule/OfflineFallback.php index b09504e..3feef82 100644 --- a/src/Service/Rule/OfflineFallback.php +++ b/src/Service/Rule/OfflineFallback.php @@ -4,6 +4,7 @@ namespace SpomkyLabs\PwaBundle\Service\Rule; +use SpomkyLabs\PwaBundle\Dto\ServiceWorker; use SpomkyLabs\PwaBundle\Dto\Workbox; use Symfony\Component\DependencyInjection\Attribute\Autowire; use Symfony\Component\Serializer\Encoder\JsonEncode; @@ -16,18 +17,22 @@ use const JSON_UNESCAPED_UNICODE; use const PHP_EOL; -final readonly class OfflineFallback implements WorkboxRule +final readonly class OfflineFallback implements ServiceWorkerRule { /** * @var array */ private array $jsonOptions; + private Workbox $workbox; + public function __construct( + ServiceWorker $serviceWorker, private SerializerInterface $serializer, #[Autowire('%kernel.debug%')] bool $debug, ) { + $this->workbox = $serviceWorker->workbox; $options = [ AbstractObjectNormalizer::SKIP_UNINITIALIZED_VALUES => true, AbstractObjectNormalizer::SKIP_NULL_VALUES => true, @@ -39,15 +44,18 @@ public function __construct( $this->jsonOptions = $options; } - public function process(Workbox $workbox, string $body): string + public function process(string $body): string { - if ($workbox->offlineFallback->enabled === false) { + if ($this->workbox->enabled === false) { + return $body; + } + if ($this->workbox->offlineFallback->enabled === false) { return $body; } $options = [ - 'pageFallback' => $workbox->offlineFallback->pageFallback, - 'imageFallback' => $workbox->offlineFallback->imageFallback, - 'fontFallback' => $workbox->offlineFallback->fontFallback, + 'pageFallback' => $this->workbox->offlineFallback->pageFallback, + 'imageFallback' => $this->workbox->offlineFallback->imageFallback, + 'fontFallback' => $this->workbox->offlineFallback->fontFallback, ]; $options = array_filter($options, static fn (mixed $v): bool => $v !== null); $options = count($options) === 0 ? '' : $this->serializer->serialize($options, 'json', $this->jsonOptions); diff --git a/src/Service/Rule/PageCache.php b/src/Service/Rule/PageCache.php index f32c8c6..6f615af 100644 --- a/src/Service/Rule/PageCache.php +++ b/src/Service/Rule/PageCache.php @@ -4,7 +4,10 @@ namespace SpomkyLabs\PwaBundle\Service\Rule; +use SpomkyLabs\PwaBundle\Dto\ServiceWorker; use SpomkyLabs\PwaBundle\Dto\Workbox; +use SpomkyLabs\PwaBundle\Service\CacheStrategy; +use SpomkyLabs\PwaBundle\Service\HasCacheStrategies; use Symfony\Component\DependencyInjection\Attribute\Autowire; use Symfony\Component\Serializer\Encoder\JsonEncode; use Symfony\Component\Serializer\Normalizer\AbstractObjectNormalizer; @@ -15,18 +18,22 @@ use const JSON_UNESCAPED_UNICODE; use const PHP_EOL; -final readonly class PageCache implements WorkboxRule +final readonly class PageCache implements ServiceWorkerRule, HasCacheStrategies { /** * @var array */ private array $jsonOptions; + private Workbox $workbox; + public function __construct( + ServiceWorker $serviceWorker, private SerializerInterface $serializer, #[Autowire('%kernel.debug%')] bool $debug, ) { + $this->workbox = $serviceWorker->workbox; $options = [ AbstractObjectNormalizer::SKIP_UNINITIALIZED_VALUES => true, AbstractObjectNormalizer::SKIP_NULL_VALUES => true, @@ -38,21 +45,40 @@ public function __construct( $this->jsonOptions = $options; } - public function process(Workbox $workbox, string $body): string + public function process(string $body): string { - if ($workbox->pageCache->enabled === false) { + if ($this->workbox->enabled === false) { + return $body; + } + if ($this->workbox->pageCache->enabled === false) { return $body; } - $routes = $this->serializer->serialize($workbox->pageCache->urls, 'json', $this->jsonOptions); + $routes = $this->serializer->serialize($this->workbox->pageCache->urls, 'json', $this->jsonOptions); $declaration = <<pageCache->cacheName}', - networkTimeoutSeconds: {$workbox->pageCache->networkTimeout}, + cacheName: '{$this->workbox->pageCache->cacheName}', + networkTimeoutSeconds: {$this->workbox->pageCache->networkTimeout}, warmCache: {$routes} }); PAGE_CACHE_RULE_STRATEGY; return $body . PHP_EOL . PHP_EOL . trim($declaration); } + + public function getCacheStrategies(): array + { + return [ + CacheStrategy::create( + $this->workbox->pageCache->cacheName, + CacheStrategy::STRATEGY_STALE_WHILE_REVALIDATE, + "'({request}) => request.mode === 'navigate'", + $this->workbox->enabled && $this->workbox->pageCache->enabled, + true, + [ + 'maxTimeout' => $this->workbox->pageCache->networkTimeout, + ] + ), + ]; + } } diff --git a/src/Service/Rule/WorkboxImport.php b/src/Service/Rule/WorkboxImport.php index 86b5649..d424c19 100644 --- a/src/Service/Rule/WorkboxImport.php +++ b/src/Service/Rule/WorkboxImport.php @@ -4,19 +4,31 @@ namespace SpomkyLabs\PwaBundle\Service\Rule; +use SpomkyLabs\PwaBundle\Dto\ServiceWorker; use SpomkyLabs\PwaBundle\Dto\Workbox; use const PHP_EOL; -final readonly class WorkboxImport implements WorkboxRule +final readonly class WorkboxImport implements ServiceWorkerRule { - public function process(Workbox $workbox, string $body): string + private Workbox $workbox; + + public function __construct( + ServiceWorker $serviceWorker + ) { + $this->workbox = $serviceWorker->workbox; + } + + public function process(string $body): string { - if ($workbox->useCDN === true) { + if ($this->workbox->enabled === false) { + return $body; + } + if ($this->workbox->useCDN === true) { $declaration = <<version}/workbox-sw.js'); +importScripts('https://storage.googleapis.com/workbox-cdn/releases/{$this->workbox->version}/workbox-sw.js'); IMPORT_CDN_STRATEGY; } else { - $publicUrl = '/' . trim($workbox->workboxPublicUrl, '/'); + $publicUrl = '/' . trim($this->workbox->workboxPublicUrl, '/'); $declaration = << $serviceworkerRules - * @param iterable $workboxRules */ public function __construct( #[Autowire('%spomky_labs_pwa.sw.enabled%')] @@ -26,8 +24,6 @@ public function __construct( private AssetMapperInterface $assetMapper, #[TaggedIterator('spomky_labs_pwa.service_worker_rule', defaultPriorityMethod: 'getPriority')] private iterable $serviceworkerRules, - #[TaggedIterator('spomky_labs_pwa.workbox_rule', defaultPriorityMethod: 'getPriority')] - private iterable $workboxRules, ) { } @@ -46,12 +42,6 @@ public function compile(): ?string $body = file_get_contents($serviceWorker->src->src); } assert(is_string($body), 'Unable to find service worker source content'); - $workbox = $serviceWorker->workbox; - if ($workbox->enabled === true) { - foreach ($this->workboxRules as $rule) { - $body = $rule->process($workbox, $body); - } - } foreach ($this->serviceworkerRules as $rule) { $body = $rule->process($body); }