Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simplified SW skeleton #49

Merged
merged 1 commit into from
Jan 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions phpstan-baseline.neon
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,11 @@ parameters:
count: 1
path: src/Dto/Workbox.php

-
message: "#^Class SpomkyLabs\\\\PwaBundle\\\\Dto\\\\Workbox has an uninitialized property \\$standardRulesPlaceholder\\. Give it default value or assign it in the constructor\\.$#"
count: 1
path: src/Dto/Workbox.php

-
message: "#^Class SpomkyLabs\\\\PwaBundle\\\\Dto\\\\Workbox has an uninitialized property \\$useCDN\\. Give it default value or assign it in the constructor\\.$#"
count: 1
Expand Down
7 changes: 7 additions & 0 deletions src/DependencyInjection/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -493,6 +493,13 @@ private function setupServiceWorker(ArrayNodeDefinition $node): void
)
->example('//WORKBOX_IMPORT_PLACEHOLDER')
->end()
->scalarNode('standard_rules_placeholder')
->defaultValue('//STANDARD_RULES_PLACEHOLDER')
->info(
'The placeholder for the standard rules. Will be replaced by caching strategies.'
)
->example('//STANDARD_RULES_PLACEHOLDER')
->end()
->scalarNode('precaching_placeholder')
->defaultValue('//PRECACHING_PLACEHOLDER')
->info(
Expand Down
3 changes: 3 additions & 0 deletions src/Dto/Workbox.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ final class Workbox
#[SerializedName('warm_cache_placeholder')]
public string $warmCachePlaceholder;

#[SerializedName('standard_rules_placeholder')]
public string $standardRulesPlaceholder;

#[SerializedName('precaching_placeholder')]
public string $precachingPlaceholder;

Expand Down
47 changes: 2 additions & 45 deletions src/Resources/sw-skeleton.js
Original file line number Diff line number Diff line change
@@ -1,49 +1,6 @@
// *** Workbox ***
// Workbox is imported from a CDN or local files.
// *** Workbox Bundle rules ***
//WORKBOX_IMPORT_PLACEHOLDER

// *** Recipes ***
// You are free to change or remove any of these presets as you wish.
// See https://developer.chrome.com/docs/workbox/modules/workbox-recipes for more information.
const {
pageCache,
imageCache,
googleFontsCache,
} = workbox.recipes;
const {registerRoute} = workbox.routing;
const {CacheFirst} = workbox.strategies;
const {CacheableResponsePlugin} = workbox.cacheableResponse;

pageCache();// => Cache pages with a network-first strategy.
imageCache();// => Cache images with a cache-first strategy.
googleFontsCache();// => Cache the underlying font files with a cache-first strategy.

// *** Assets ***
// Cache CSS, JS, and Web Worker requests with a cache-first strategy.
// We could use staticResourceCache();, but this strategy uses a stale-while-revalidate strategy,
// which is not ideal for static resources served by Asset Mapper (assets are immutable)
const cacheName = 'static-resources';
const matchCallback = ({request}) =>
// CSS
request.destination === 'style' ||
// JavaScript
request.destination === 'script' ||
// Web Workers
request.destination === 'worker';

registerRoute(
matchCallback,
new CacheFirst({
cacheName,
plugins: [
new CacheableResponsePlugin({
statuses: [0, 200],
}),
],
})
);

// *** Bundle rules ***
//STANDARD_RULES_PLACEHOLDER
//PRECACHING_PLACEHOLDER
//WARM_CACHE_URLS_PLACEHOLDER
//OFFLINE_FALLBACK_PLACEHOLDER
Expand Down
73 changes: 32 additions & 41 deletions src/Service/ServiceWorkerBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,13 +53,41 @@ public function build(): ?string
private function processWorkbox(Workbox $workbox, string $body): string
{
$body = $this->processWorkboxImport($workbox, $body);
$body = $this->processStandardRules($workbox, $body);
$body = $this->processPrecachedAssets($workbox, $body);
$body = $this->processWarmCacheUrls($workbox, $body);
$body = $this->processWidgets($workbox, $body);

return $this->processOfflineFallback($workbox, $body);
}

private function processStandardRules(Workbox $workbox, string $body): string
{
if (! str_contains($body, $workbox->standardRulesPlaceholder)) {
return $body;
}

$declaration = <<<STANDARD_RULE_STRATEGY
workbox.recipes.pageCache();
workbox.recipes.imageCache();
workbox.recipes.googleFontsCache();
const matchCallback = ({request}) => request.destination === 'style' || request.destination === 'script' || request.destination === 'worker';
workbox.routing.registerRoute(
matchCallback,
new workbox.strategies.CacheFirst({
cacheName: 'static-resources',
plugins: [
new workbox.cacheableResponse.CacheableResponsePlugin({
statuses: [0, 200],
}),
],
})
);
STANDARD_RULE_STRATEGY;

return str_replace($workbox->standardRulesPlaceholder, trim($declaration), $body);
}

private function processPrecachedAssets(Workbox $workbox, string $body): string
{
if (! str_contains($body, $workbox->precachingPlaceholder)) {
Expand All @@ -75,14 +103,9 @@ private function processPrecachedAssets(Workbox $workbox, string $body): string
$assets = $this->serializer->serialize($result, 'json', [
JsonEncode::OPTIONS => JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR,
]);
$precacheAndRouteDeclaration = str_contains(
$body,
'precacheAndRoute'
) ? '' : 'const { precacheAndRoute } = workbox.precaching;';

$declaration = <<<PRECACHE_STRATEGY
{$precacheAndRouteDeclaration}
precacheAndRoute({$assets});
workbox.precaching.precacheAndRoute({$assets});
PRECACHE_STRATEGY;

return str_replace($workbox->precachingPlaceholder, trim($declaration), $body);
Expand All @@ -102,21 +125,10 @@ private function processWarmCacheUrls(Workbox $workbox, string $body): string
JsonEncode::OPTIONS => JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR,
]);

$cacheFirstStrategyDeclaration = str_contains(
$body,
'CacheFirst'
) ? '' : 'const { CacheFirst } = workbox.strategies;';
$warmStrategyCacheMethod = str_contains(
$body,
'warmStrategyCache'
) ? '' : 'const { warmStrategyCache } = workbox.recipes;';

$declaration = <<<WARM_CACHE_URL_STRATEGY
{$cacheFirstStrategyDeclaration}
{$warmStrategyCacheMethod}
warmStrategyCache({
workbox.recipes.warmStrategyCache({
urls: {$routes},
strategy: new CacheFirst()
strategy: new workbox.strategies.CacheFirst()
});
WARM_CACHE_URL_STRATEGY;

Expand All @@ -133,27 +145,7 @@ private function processOfflineFallback(Workbox $workbox, string $body): string
JsonEncode::OPTIONS => JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR,
]);

$offlineFallbackMethod = str_contains(
$body,
'offlineFallback'
) ? '' : 'const { offlineFallback } = workbox.recipes;';
$networkOnlyStrategy = str_contains(
$body,
'NetworkOnly'
) ? '' : 'const { NetworkOnly } = workbox.strategies;';
$setDefaultHandlerRouting = str_contains(
$body,
'setDefaultHandler'
) ? '' : 'const { setDefaultHandler } = workbox.routing;' . PHP_EOL . 'setDefaultHandler(new NetworkOnly());';

$declaration = <<<OFFLINE_FALLBACK_STRATEGY
{$offlineFallbackMethod}
{$networkOnlyStrategy}
{$setDefaultHandlerRouting}
offlineFallback({
pageFallback: {$url},
});
OFFLINE_FALLBACK_STRATEGY;
$declaration = sprintf('%sworkbox.recipes.offlineFallback({ pageFallback: %s });', PHP_EOL, $url);

return str_replace($workbox->offlineFallbackPlaceholder, trim($declaration), $body);
}
Expand Down Expand Up @@ -251,7 +243,6 @@ private function processWorkboxImport(Workbox $workbox, string $body): string
);
IMPORT_CDN_STRATEGY;
} else {
$version = $workbox->version;
$publicUrl = '/' . trim($workbox->workboxPublicUrl, '/');
$declaration = <<<IMPORT_CDN_STRATEGY
importScripts('{$publicUrl}/workbox-sw.js');
Expand Down
36 changes: 2 additions & 34 deletions tests/sw.js
Original file line number Diff line number Diff line change
@@ -1,38 +1,6 @@
// *** Workbox Bundle rules ***
//WORKBOX_IMPORT_PLACEHOLDER
const {
pageCache,
imageCache,
googleFontsCache,
} = workbox.recipes;
const {registerRoute} = workbox.routing;
const {CacheFirst} = workbox.strategies;
const {CacheableResponsePlugin} = workbox.cacheableResponse;

pageCache();
imageCache();
googleFontsCache();

const cacheName = 'static-resources';
const matchCallback = ({request}) =>
// CSS
request.destination === 'style' ||
// JavaScript
request.destination === 'script' ||
// Web Workers
request.destination === 'worker';

registerRoute(
matchCallback,
new CacheFirst({
cacheName,
plugins: [
new CacheableResponsePlugin({
statuses: [0, 200],
}),
],
})
);

//STANDARD_RULES_PLACEHOLDER
//PRECACHING_PLACEHOLDER
//WARM_CACHE_URLS_PLACEHOLDER
//OFFLINE_FALLBACK_PLACEHOLDER
Expand Down
Loading