Skip to content

Commit

Permalink
Simplifies the SW build
Browse files Browse the repository at this point in the history
  • Loading branch information
Spomky committed Dec 30, 2023
1 parent 0bc6a6b commit 048434c
Show file tree
Hide file tree
Showing 5 changed files with 204 additions and 104 deletions.
83 changes: 58 additions & 25 deletions src/Command/GenerateManifestCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@
use SpomkyLabs\PwaBundle\ImageProcessor\ImageProcessor;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Helper\ProgressBar;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
use Symfony\Component\DependencyInjection\Attribute\Autowire;
use Symfony\Component\Filesystem\Exception\IOExceptionInterface;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\Finder\Finder;
use Symfony\Component\HttpKernel\Config\FileLocator;
use Symfony\Component\Mime\MimeTypes;
use Symfony\Component\Routing\RouterInterface;
use function count;
Expand All @@ -40,6 +40,7 @@ public function __construct(
#[Autowire('%spomky_labs_pwa.dest%')]
private readonly array $dest,
private readonly Filesystem $filesystem,
private readonly FileLocator $fileLocator,
private readonly ?RouterInterface $router = null,
) {
$this->mime = MimeTypes::getDefault();
Expand Down Expand Up @@ -69,6 +70,10 @@ protected function execute(InputInterface $input, OutputInterface $output): int
if (! is_array($manifest)) {
return self::FAILURE;
}
$manifest = $this->processServiceWorker($io, $manifest);
if (! is_array($manifest)) {
return self::FAILURE;
}

try {
$this->createDirectoryIfNotExists(dirname((string) $this->dest['manifest_filepath']));
Expand Down Expand Up @@ -203,12 +208,7 @@ private function processIcons(SymfonyStyle $io, array $manifest): array|int
return self::FAILURE;
}
$manifest['icons'] = [];
$progressBar = $io->createProgressBar(count($this->config['icons']));
$progressBar->start();
$io->info('Processing icons');
$progressBar->start();
foreach ($this->config['icons'] as $icon) {
$this->processProgressBar($progressBar, 'icon', $icon['src']);
foreach ($icon['sizes'] as $size) {
if (! is_int($size) || $size < 0) {
$io->error('The icon size must be a positive integer');
Expand All @@ -224,7 +224,6 @@ private function processIcons(SymfonyStyle $io, array $manifest): array|int
$manifest['icons'][] = $iconManifest;
}
}
$progressBar->finish();
$io->info('Icons are built');

return $manifest;
Expand All @@ -241,9 +240,6 @@ private function processScreenshots(SymfonyStyle $io, array $manifest): array|in
return self::FAILURE;
}
$manifest['screenshots'] = [];
$progressBar = $io->createProgressBar(count($this->config['screenshots']));
$progressBar->start();
$io->info('Processing screenshots');
$config = [];
foreach ($this->config['screenshots'] as $screenshot) {
$src = $screenshot['src'];
Expand All @@ -258,7 +254,6 @@ private function processScreenshots(SymfonyStyle $io, array $manifest): array|in
}

foreach ($config as $screenshot) {
$this->processProgressBar($progressBar, 'screenshot', $screenshot['src']);
$data = $this->loadFileAndConvert($screenshot['src'], null, $screenshot['format'] ?? null);
if ($data === null) {
$io->error(sprintf('Unable to read the icon "%s"', $screenshot['src']));
Expand All @@ -277,7 +272,6 @@ private function processScreenshots(SymfonyStyle $io, array $manifest): array|in
}
$manifest['screenshots'][] = $screenshotManifest;
}
$progressBar->finish();

return $manifest;
}
Expand All @@ -293,11 +287,7 @@ private function processShortcutIcons(SymfonyStyle $io, array|int $manifest): ar
return self::FAILURE;
}
$manifest['shortcuts'] = [];
$progressBar = $io->createProgressBar(count($this->config['shortcuts']));
$io->info('Processing shortcuts');
$progressBar->start();
foreach ($this->config['shortcuts'] as $shortcutConfig) {
$this->processProgressBar($progressBar, 'shortcuts', $shortcutConfig['name']);
$shortcut = $shortcutConfig;
if (isset($shortcut['icons'])) {
unset($shortcut['icons']);
Expand Down Expand Up @@ -334,7 +324,6 @@ private function processShortcutIcons(SymfonyStyle $io, array|int $manifest): ar
}
$manifest['shortcuts'][] = $shortcut;
}
$progressBar->finish();
$manifest['shortcuts'] = array_values($manifest['shortcuts']);

return $manifest;
Expand Down Expand Up @@ -376,24 +365,17 @@ private function createDirectoryIfNotExists(string $folder): bool
return true;
}

private function processProgressBar(ProgressBar $progressBar, string $type, string $src): void
{
$progressBar->advance();
$progressBar->setMessage(sprintf('Processing %s %s', $type, $src));
}

private function processActions(SymfonyStyle $io, array $manifest): array|int
{
if ($this->config['file_handlers'] === []) {
return $manifest;
}
$io->info('Processing file handlers');
foreach ($manifest['file_handlers'] as $id => $handler) {
if (str_starts_with((string) $handler['action'], '/')) {
continue;
}
if ($this->router === null) {
$io->error('The router is not available');
$io->error('The router is not available. Unable to generate the file handler action URL.');
return self::FAILURE;
}
$manifest['file_handlers'][$id]['action'] = $this->router->generate(
Expand Down Expand Up @@ -427,4 +409,55 @@ private function findImages(string $src): iterable
}
}
}

private function processServiceWorker(SymfonyStyle $io, array $manifest): int|array
{
if (! isset($manifest['serviceworker'])) {
$io->error('Service worker generation is disabled. Skipping.');
return $manifest;
}
$generate = $manifest['serviceworker']['generate'];
unset($manifest['serviceworker']['generate']);

if ($generate !== true) {
$io->info('Service worker generation is disabled. Skipping.');
return $manifest;
}

$dest = $manifest['serviceworker']['filepath'];
$scope = $manifest['serviceworker']['scope'];
$src = $manifest['serviceworker']['src'];
unset($manifest['serviceworker']['filepath']);

if (! $this->filesystem->exists(dirname((string) $dest))) {
$this->filesystem->mkdir(dirname((string) $dest));
}
if ($this->filesystem->exists($dest)) {
$io->info('Service worker already exists. Skipping.');
return $manifest;
}

$resourcePath = $this->fileLocator->locate('@SpomkyLabsPwaBundle/Resources/workbox.js', null, false);
if (count($resourcePath) !== 1) {
$io->error('Unable to find the Workbox resource.');
return self::FAILURE;
}
$resourcePath = $resourcePath[0];
$this->filesystem->copy($resourcePath, $dest);
$io->info('Service worker generated.');
$io->comment('You can now configure your web server to serve the service worker file.');
$io->section('# assets/app.js (or any other entrypoint)');
$jsTemplate = <<<JS
if (navigator.serviceWorker) {
window.addEventListener("load", () => {
navigator.serviceWorker.register("{$src}", {scope: '{$scope}'});
})
}
JS;

$io->writeln($jsTemplate);
$io->section('# End of file');

return $manifest;
}
}
51 changes: 0 additions & 51 deletions src/Command/WorkboxInitCommand.php

This file was deleted.

62 changes: 52 additions & 10 deletions src/DependencyInjection/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ private function setupShortcuts(ArrayNodeDefinition $node): void
{
$node->children()
->arrayNode('shortcuts')
->treatFalseLike([])
->treatTrueLike([])
->treatNullLike([])
->info('The shortcuts of the application.')
->arrayPrototype()
->children()
Expand Down Expand Up @@ -75,6 +78,9 @@ private function setupScreenshots(ArrayNodeDefinition $node): void
{
$node->children()
->arrayNode('screenshots')
->treatFalseLike([])
->treatTrueLike([])
->treatNullLike([])
->info('The screenshots of the application.')
->arrayPrototype()
->children()
Expand Down Expand Up @@ -113,6 +119,9 @@ private function setupFileHandlers(ArrayNodeDefinition $node): void
->info(
'It specifies an array of objects representing the types of files an installed progressive web app (PWA) can handle.'
)
->treatFalseLike([])
->treatTrueLike([])
->treatNullLike([])
->arrayPrototype()
->children()
->scalarNode('action')
Expand Down Expand Up @@ -140,6 +149,9 @@ private function setupSharedTarget(ArrayNodeDefinition $node): void
{
$node->children()
->arrayNode('share_target')
->treatFalseLike([])
->treatTrueLike([])
->treatNullLike([])
->info('The share target of the application.')
->children()
->scalarNode('action')
Expand Down Expand Up @@ -195,6 +207,9 @@ private function setupProtocolHandlers(ArrayNodeDefinition $node): void
{
$node->children()
->arrayNode('protocol_handlers')
->treatFalseLike([])
->treatTrueLike([])
->treatNullLike([])
->info('The protocol handlers of the application.')
->arrayPrototype()
->children()
Expand All @@ -218,6 +233,9 @@ private function setupLaunchHandler(ArrayNodeDefinition $node): void
{
$node->children()
->arrayNode('launch_handler')
->treatFalseLike([])
->treatTrueLike([])
->treatNullLike([])
->info('The launch handler of the application.')
->children()
->arrayNode('client_mode')
Expand All @@ -237,9 +255,12 @@ private function setupRelatedApplications(ArrayNodeDefinition $node): void
{
$node->children()
->booleanNode('prefer_related_applications')
->info('The prefer related native applications of the application.')
->info('The prefer related native applications of the application.')
->end()
->arrayNode('related_applications')
->treatFalseLike([])
->treatTrueLike([])
->treatNullLike([])
->info('The related applications of the application.')
->arrayPrototype()
->children()
Expand Down Expand Up @@ -297,13 +318,9 @@ private function setupSimpleOptions(ArrayNodeDefinition $node): void
->info('The URL prefix to use to generate the icons.')
->end()
->scalarNode('manifest_filepath')
->defaultValue('%kernel.project_dir%/public/pwa.json')
->defaultValue('%kernel.project_dir%/public/site.webmanifest')
->info('The filename where the manifest will be generated.')
->end()
->scalarNode('serviceworker_filepath')
->defaultValue('%kernel.project_dir%/public/sw.js')
->info('The filename where the service worker will be generated.')
->end()
->scalarNode('background_color')
->info(
'The background color of the application. It should match the background-color CSS property in the sites stylesheet for a smooth transition between launching the web application and loading the site\'s content.'
Expand Down Expand Up @@ -374,6 +391,9 @@ private function getIconsNode(): ArrayNodeDefinition
$node = $treeBuilder->getRootNode();
assert($node instanceof ArrayNodeDefinition);
$node
->treatFalseLike([])
->treatTrueLike([])
->treatNullLike([])
->arrayPrototype()
->children()
->scalarNode('src')
Expand Down Expand Up @@ -407,19 +427,41 @@ private function setupServiceWorker(ArrayNodeDefinition $node): void
{
$node->children()
->arrayNode('serviceworker')
->info(
'EXPERIMENTAL. Specifies a serviceworker that is Just-In-Time (JIT)-installed and registered to run a web-based payment app providing a payment mechanism for a specified payment method in a merchant website.'
)
->info('EXPERIMENTAL. Specifies a serviceworker that is registered.')
->treatFalseLike([])
->treatTrueLike([
'generate' => true,
])
->treatNullLike([])
->validate()
->ifTrue(
static fn (array $v): bool => basename((string) $v['filepath']) !== basename((string) $v['src'])
)
->thenInvalid('The filename from the "filepath" and the "src" must be the same.')
->end()
->children()
->booleanNode('generate')
->defaultFalse()
->info('Whether the service worker should be generated.')
->end()
->scalarNode('filepath')
->defaultValue('%kernel.project_dir%/public/sw.js')
->info('The filename where the service worker will be generated.')
->end()
->scalarNode('src')
->cannotBeEmpty()
->defaultValue('/sw.js')
->info('The path to the service worker.')
->example('sw.js')
->example('/sw.js')
->end()
->scalarNode('scope')
->cannotBeEmpty()
->defaultValue('/')
->info('The scope of the service worker.')
->example('/app/')
->end()
->booleanNode('use_cache')
->defaultTrue()
->info('Whether the service worker should use the cache.')
->end()
->end()
Expand Down
Loading

0 comments on commit 048434c

Please sign in to comment.