Skip to content

Commit

Permalink
Merge pull request #88 from Spomky-Labs/temp-a39def9
Browse files Browse the repository at this point in the history
Merge-up 1.0.x to 1.1.x
  • Loading branch information
Spomky authored Mar 4, 2024
2 parents 024aaf4 + f53c6cd commit 8536bf7
Show file tree
Hide file tree
Showing 5 changed files with 117 additions and 31 deletions.
8 changes: 8 additions & 0 deletions .github/workflows/release-on-milestone-closed.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ jobs:
steps:
- name: "Checkout"
uses: "actions/checkout@v4"
with:
fetch-depth: 0

- name: "Release"
uses: "laminas/[email protected]"
Expand All @@ -36,6 +38,8 @@ jobs:
steps:
- name: "Checkout"
uses: "actions/checkout@v4"
with:
fetch-depth: 0

- name: "Create Merge-Up Pull Request"
uses: "laminas/[email protected]"
Expand All @@ -57,6 +61,8 @@ jobs:
steps:
- name: "Checkout"
uses: "actions/checkout@v4"
with:
fetch-depth: 0

- name: "Create and/or Switch to new Release Branch"
uses: "laminas/[email protected]"
Expand Down Expand Up @@ -101,6 +107,8 @@ jobs:
steps:
- name: "Checkout"
uses: "actions/checkout@v4"
with:
fetch-depth: 0

- name: "Create new milestones"
uses: "laminas/[email protected]"
Expand Down
7 changes: 6 additions & 1 deletion src/DependencyInjection/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -175,10 +175,15 @@ private function setupServiceWorker(ArrayNodeDefinition $node): void
->example('/\.(ico|png|jpe?g|gif|svg|webp|bmp)$/')
->end()
->scalarNode('static_regex')
->defaultValue('/\.(css|js|json|xml|txt|woff2|ttf|eot|otf|map|webmanifest)$/')
->defaultValue('/\.(css|js|json|xml|txt|map|webmanifest)$/')
->info('The regex to match the static files.')
->example('/\.(css|js|json|xml|txt|woff2|ttf|eot|otf|map|webmanifest)$/')
->end()
->scalarNode('font_regex')
->defaultValue('/\.(ttf|eot|otf|woff2)$/')
->info('The regex to match the static files.')
->example('/\.(ttf|eot|otf|woff2)$/')
->end()
->integerNode('max_image_cache_entries')
->defaultValue(60)
->info('The maximum number of entries in the image cache.')
Expand Down
5 changes: 4 additions & 1 deletion src/Dto/Workbox.php
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,10 @@ final class Workbox
public string $imageRegex = '/\.(ico|png|jpe?g|gif|svg|webp|bmp)$/';

#[SerializedName('static_regex')]
public string $staticRegex = '/\.(css|m?jsx?|json|xml|txt|woff2|ttf|eot|otf|map|webmanifest)$/';
public string $staticRegex = '/\.(css|m?jsx?|json|xml|txt|map|webmanifest)$/';

#[SerializedName('font_regex')]
public string $fontRegex = '/\.(ttf|eot|otf|woff2)$/';

#[SerializedName('clear_cache')]
public bool $clearCache = true;
Expand Down
105 changes: 80 additions & 25 deletions src/Service/ServiceWorkerCompiler.php
Original file line number Diff line number Diff line change
Expand Up @@ -130,53 +130,108 @@ private function processStandardRules(Workbox $workbox, string $body): string
return $body;
}

$images = [];
$statics = [];
$assets = [];
$fonts = [];
foreach ($this->assetMapper->allAssets() as $asset) {
if (preg_match($workbox->imageRegex, $asset->sourcePath) === 1) {
$images[] = $asset->publicPath;
} elseif (preg_match($workbox->staticRegex, $asset->sourcePath) === 1) {
$statics[] = $asset->publicPath;
if (preg_match($workbox->imageRegex, $asset->sourcePath) === 1 || preg_match(
$workbox->staticRegex,
$asset->sourcePath
) === 1) {
$assets[] = $asset->publicPath;
} elseif (preg_match($workbox->fontRegex, $asset->sourcePath) === 1) {
$fonts[] = $asset->publicPath;
}
}
$jsonOptions = [
JsonEncode::OPTIONS => JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR,
];
$imageUrls = $this->serializer->serialize($images, 'json', $jsonOptions);
$staticUrls = $this->serializer->serialize($statics, 'json', $jsonOptions);
$assetUrls = $this->serializer->serialize($assets, 'json', $jsonOptions);
$fontUrls = $this->serializer->serialize($fonts, 'json', $jsonOptions);
$assetUrlsLength = count($assets) * 2;
$routes = $this->serializer->serialize($workbox->warmCacheUrls, 'json', $jsonOptions);

$declaration = <<<STANDARD_RULE_STRATEGY
// Pages cached during the navigation.
workbox.recipes.pageCache({
cacheName: '{$workbox->pageCacheName}',
networkTimeoutSeconds: {$workbox->networkTimeoutSeconds},
warmCache: {$routes}
});
workbox.recipes.imageCache({
cacheName: '{$workbox->imageCacheName}',
maxEntries: {$workbox->maxImageCacheEntries},
maxImageAge: {$workbox->maxImageAge},
warmCache: {$imageUrls}
});
workbox.recipes.staticResourceCache({
cacheName: '{$workbox->assetCacheName}',
warmCache: {$staticUrls}
});
//Images cache
workbox.routing.registerRoute(
({request}) => request.destination === 'font',
({request, url}) => (request.destination === 'image' && !url.pathname.startsWith('/assets')),
new workbox.strategies.CacheFirst({
cacheName: '{$workbox->fontCacheName}',
cacheName: '{$workbox->imageCacheName}',
plugins: [
new workbox.cacheableResponse.CacheableResponsePlugin({
statuses: [0, 200],
}),
new workbox.cacheableResponse.CacheableResponsePlugin({statuses: [0, 200]}),
new workbox.expiration.ExpirationPlugin({
maxAgeSeconds: {$workbox->maxFontAge},
maxEntries: {$workbox->maxFontCacheEntries},
maxEntries: {$workbox->maxImageCacheEntries},
maxAgeSeconds: {$workbox->maxImageAge},
}),
],
})
);
// Assets served by Asset Mapper
// - Strategy: CacheFirst
const assetCacheStrategy = new workbox.strategies.CacheFirst({
cacheName: '{$workbox->assetCacheName}',
plugins: [
new workbox.cacheableResponse.CacheableResponsePlugin({statuses: [0, 200]}),
new workbox.expiration.ExpirationPlugin({
maxEntries: {$assetUrlsLength},
maxAgeSeconds: 365 * 24 * 60 * 60,
}),
],
});
// - Strategy: only the Asset Mapper public route
workbox.routing.registerRoute(
({url}) => url.pathname.startsWith('/assets'),
assetCacheStrategy
);
self.addEventListener('install', event => {
const done = {$assetUrls}.map(
path =>
assetCacheStrategy.handleAll({
event,
request: new Request(path),
})[1]
);
event.waitUntil(Promise.all(done));
});
const fontCacheStrategy = new workbox.strategies.CacheFirst({
cacheName: '{$workbox->fontCacheName}',
plugins: [
new workbox.cacheableResponse.CacheableResponsePlugin({
statuses: [0, 200],
}),
new workbox.expiration.ExpirationPlugin({
maxAgeSeconds: {$workbox->maxFontAge},
maxEntries: {$workbox->maxFontCacheEntries},
}),
],
});
workbox.routing.registerRoute(
({request}) => request.destination === 'font',
fontCacheStrategy
);
self.addEventListener('install', event => {
const done = {$fontUrls}.map(
path =>
fontCacheStrategy.handleAll({
event,
request: new Request(path),
})[1]
);
event.waitUntil(Promise.all(done));
});
STANDARD_RULE_STRATEGY;

return str_replace($workbox->standardRulesPlaceholder, trim($declaration), $body);
Expand Down
23 changes: 19 additions & 4 deletions src/Twig/PwaRuntime.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@
private string $manifestPublicUrl;

public function __construct(
#[Autowire('%spomky_labs_pwa.manifest.enabled%')]
private bool $manifestEnabled,
#[Autowire('%spomky_labs_pwa.sw.enabled%')]
private bool $serviceWorkerEnabled,
#[Autowire('@asset_mapper.importmap.config_reader')]
private ImportMapConfigReader $importMapConfigReader,
private AssetMapperInterface $assetMapper,
Expand All @@ -40,12 +44,23 @@ public function load(
bool $injectSW = true,
array $swAttributes = []
): string {
$url = $this->assetMapper->getPublicPath($this->manifestPublicUrl) ?? $this->manifestPublicUrl;
$output = sprintf('%s<link rel="manifest" href="%s">', PHP_EOL, $url);
$output = '';
if ($this->manifestEnabled === true) {
$output = $this->injectManifestFile($output);
}
if ($this->serviceWorkerEnabled === true) {
$output = $this->injectServiceWorker($output, $injectSW, $swAttributes);
}
$output = $this->injectIcons($output, $injectIcons);
$output = $this->injectThemeColor($output, $injectThemeColor);

return $this->injectServiceWorker($output, $injectSW, $swAttributes);
return $this->injectThemeColor($output, $injectThemeColor);
}

private function injectManifestFile(string $output): string
{
$url = $this->assetMapper->getPublicPath($this->manifestPublicUrl) ?? $this->manifestPublicUrl;

return $output . sprintf('%s<link rel="manifest" href="%s">', PHP_EOL, $url);
}

private function injectThemeColor(string $output, bool $themeColor): string
Expand Down

0 comments on commit 8536bf7

Please sign in to comment.