From 1.5.x to 1.6.0¶
This page describes the changes you need to make when upgrading from version 1.5.x to 1.6.0.
Success
Nothing is removed in 1.6.0. Everything below keeps working exactly as before. The release exists to give you a full minor version to migrate before 2.0.0 takes the deprecated pieces away.
The bundle is narrowing its scope¶
The bundle is going back to what it does well: the web manifest, the service worker, and the favicons, icons and screenshots. Everything on the client-integration side is leaving.
Two things drove the decision. Wrapping a browser API in a generic, configurable Stimulus controller turns out to be a lot of abstraction for very little reuse: every project wants its own behaviour, its own UI and its own error handling. And several of those controllers push real-time, client-side interactions through the server and back, a round trip that is rarely what an application actually wants.
The full rationale is in this comment.
Deprecated: the Stimulus controllers¶
All 27 controllers shipped by the bundle are deprecated and will be removed in 2.0.0, along with
the @spomky-labs/pwa-bundle npm package.
Each one prints a warning in the browser console the first time it is mounted:
[pwa-bundle] The "pwa--web-push" Stimulus controller is deprecated since 1.6.0 and will be
removed in 2.0.0. Copy the controller into your own application and register it there.
What to do: copy the controllers you actually use into your own application and register them there. They are plain Stimulus controllers with no dependency on the bundle, so nothing is lost in the move, and you get to drop the parts you never needed.
# for instance
cp vendor/spomky-labs/pwa-bundle/assets/src/geolocation_controller.js assets/controllers/
The two page-side helpers exported through @spomky-labs/pwa/helpers, onPeriodicSync() and
registerPeriodicSync(), are deprecated too. registerPeriodicSync() is a handful of lines you
can inline:
const registration = await navigator.serviceWorker.ready;
const status = await navigator.permissions.query({ name: 'periodic-background-sync' });
if (status.state === 'granted' && 'periodicSync' in registration) {
const tags = await registration.periodicSync.getTags();
if (!tags.includes('my-tag')) {
await registration.periodicSync.register('my-tag', { minInterval: 24 * 60 * 60 * 1000 });
}
}
Deprecated: part of the service worker helpers¶
The service worker generated by the bundle used to declare a number of helper functions. Most of
them wrap events the bundle itself never handles: push, notificationclick, message,
periodicsync and the three backgroundfetch events have no producer on the PHP side.
Service worker listeners are additive, and your own source file (the src option) is appended
last, so a plain self.addEventListener() there does exactly the same job without the
indirection.
The following helpers are deprecated:
| Helper | Replacement |
|---|---|
registerCacheFirst() |
Build the strategy and call workbox.routing.registerRoute() directly |
registerMessageTask() |
self.addEventListener('message', ...) |
registerPushTask() |
self.addEventListener('push', ...) |
registerNotificationAction() |
self.addEventListener('notificationclick', ...) |
registerPeriodicSyncTask() |
self.addEventListener('periodicsync', ...) |
registerBackgroundFetchTask() |
self.addEventListener('backgroundfetchsuccess', ...) and its siblings |
openBackgroundFetchDatabase() |
Open your own database |
structuredPushNotificationSupport() |
Parse the payload and call showNotification() yourself |
simplePushNotificationSupport() |
Same |
notifyPeriodicSyncClients() |
Create your own BroadcastChannel and post to it |
Each of them warns in the console when it is actually called, so an application that already stopped using them gets a silent service worker.
What stays¶
These are not going anywhere, because your own source file cannot replace them: they either arbitrate an order between the rules the bundle generates, or carry a state shared with them.
registerInstallTask()andprecacheResources()registerCacheName(),openCache()and the newregisterClearCacheListener()statusGuard(),createBackgroundSyncPlugin()andcreateBackgroundSyncPluginWithBroadcast()- the
SKIP_WAITINGmessage handler, which is the service worker half of the update flow
Migrating¶
Replace the calls in your own service worker source:
// registerPushTask(structuredPushNotificationSupport);
self.addEventListener('push', (event) => {
const { title, options } = JSON.parse(event.data.text());
event.waitUntil(self.registration.showNotification(title, options));
});
// registerNotificationAction('*', handler);
self.addEventListener('notificationclick', (event) => {
event.notification.close();
event.waitUntil(handler(event));
});
// registerPeriodicSyncTask('my-tag', callback);
self.addEventListener('periodicsync', (event) => {
if (event.tag === 'my-tag') {
event.waitUntil(callback(event));
}
});
// registerMessageTask(callback);
self.addEventListener('message', (event) => {
event.waitUntil(callback(event));
});
Then turn the helpers off:
As long as this option is left to true, the bundle triggers a deprecation notice at container
build time. Setting it to false is what silences it, and it is the exact change 2.0.0 will make
for you.
Warning
Setting keep_deprecated_helpers to false stops the idb library from being imported into the
service worker and copied to the public folder, because openBackgroundFetchDatabase() was its
only consumer. If your own source file uses self.idb, switch to indexedDB.open() or import the
library yourself.
Deprecated: background fetch¶
The background_fetch option is deprecated and will be removed in 2.0.0.
It decides for you that a click opens a given URL, that downloads are chunked into a fixed
IndexedDB schema and that the notification title is rewritten with {title} ✅. That is a lot of
opinion for a feature every application ends up wanting differently.
pwa:
serviceworker:
workbox:
background_fetch: # deprecated since 1.6.0
enabled: true
Handle the events in your own source file instead. self.idb remains available as long as
keep_deprecated_helpers is true, and the storage is a dozen lines with plain indexedDB:
self.addEventListener('backgroundfetchsuccess', (event) => {
event.waitUntil((async () => {
const records = await event.registration.matchAll();
for (const record of records) {
const response = await record.responseReady;
// store it the way your application needs
}
await event.updateUI({ title: 'Download complete' });
})());
});
Danger
Enabling background_fetch while keep_deprecated_helpers is false now fails at container
build time with an explicit message, rather than producing a service worker that throws a
ReferenceError in the browser.
New: purging your own caches¶
clear_cache only ever deleted the caches the bundle registers itself through
registerCacheName(). A cache your own service worker source opens with caches.open() survived
every install, silently.
The new registerClearCacheListener() closes the gap. The callback receives every cache name
currently stored and returns the ones to delete:
registerClearCacheListener((names) =>
names.filter((name) => name.startsWith('my-app-') && name !== 'my-app-v3')
);
A callback rather than a list of names in the configuration, because the interesting cases are dynamic: versioned caches where the current one must survive, prefixes, anything computed at runtime.
Callbacks may be async, and one throwing is logged without stopping the others.
See Cache Cleaning.
Deprecated: favicons.use_start_image¶
The iOS startup images used to be a favicon setting, which they only ever were because they shared a source image. They now have a section of their own:
pwa:
favicons:
enabled: true
use_start_image: false # deprecated since 1.6.0
startup_images:
enabled: false # this instead
Nothing else has to move. use_start_image still seeds startup_images.enabled, and the images keep
borrowing their source, background color, border radius and SVG attributes from the favicon of the same
color scheme. An existing configuration produces the very same files, content hashes included.
New: startup images described by a Twig template¶
A startup image could only ever be the favicon source, scaled down and centered over a background color. It can now be any document you care to write:
pwa:
startup_images:
template: 'pwa/startup_image.html.twig'
context:
subtitle: 'Identify every plant, even offline.'
The template is rendered by your own Twig environment and painted by a headless Chrome driven by Panther — a compile-time dependency, and only when a template is configured. Without one, nothing new is required.
See Startup Images.
New: localized manifest members¶
The manifest can now carry every translation in a single file, through the *_localized members of the
specification, instead of one compiled file per locale:
files is the default and the historical behaviour, so nothing changes unless you ask for it.
See Translations.
Deprecated: choosing the Workbox version¶
The bundle carried two copies of the Workbox libraries, 7.0.0 and 7.3.0. Both are replaced by a single 7.4.1 copy, and choosing anything else is deprecated:
pwa:
serviceworker:
workbox:
config:
use_cdn: true # deprecated since 1.6.0
version: '7.3.0' # deprecated since 1.6.0
Everything the bundle generates — the imports, the caching strategies, the plugins, the helpers — is written against the API of the version it ships. Pinning another one produced a service worker written for one version and running against another, failing in the browser rather than at compile time.
What to do: remove both options and let the bundled files be served from your own public folder.
Then clear the stale copies, which pwa:compile writes past but never removes:
Info
The flat workbox.use_cdn and workbox.version, deprecated since 1.5.0, no longer point at their
workbox.config.* counterparts: those are deprecated too. An application still on the flat spelling is
told twice — once for the option it wrote, once for the section the value is migrated into. Removing the
option silences both.
workbox_public_url and debug are not deprecated: where your server exposes the files, and whether
Workbox logs, remain yours to decide.
See Workbox Files.
Changed: the two image processors agree on their output¶
GD and Imagick used to leave the encoding quality to their extension, so the very same configuration
produced noticeably different files: GD fell back on its default of 75, Imagick picked 92, or the quality
of the source when that source was a JPEG. Both now state 85 explicitly, and both spell jpg and
jpeg the same way.
What to do: nothing, beyond expecting your lossy images (screenshots, and any icon compiled to JPEG,
WebP or AVIF) to be regenerated with a slightly different weight on the next pwa:compile. PNG output
is unaffected.
Changed: a missing image processor extension is reported earlier¶
Pointing pwa.image_processor at a built-in processor whose PHP extension is not loaded used to fail
much later, inside the container compilation, with a bare "You have requested a non-existent service
pwa.image_processor.imagick". It now fails at configuration time, naming the missing extension.
Changed: Dto\PageCache is an alias¶
SpomkyLabs\PwaBundle\Dto\PageCache, deprecated since 1.2.0 in favour of ResourceCache, was a
subclass of a class documented as final. Symfony's DebugClassLoader told every application running in
dev or test off for an inheritance the bundle owned and they had no way to remove.
The name is now a class alias. It still resolves, still passes any instanceof ResourceCache check, and
triggers a deprecation of its own instead of a spurious one. Nothing to change beyond migrating to
ResourceCache, as 1.2.0 already asked.
Migration checklist¶
- [ ] Copy the Stimulus controllers you use into your own application, register them there
- [ ] Drop the
@spomky-labs/pwa-bundlenpm dependency once nothing imports it - [ ] Replace
onPeriodicSync()andregisterPeriodicSync()with the native calls - [ ] Replace the deprecated service worker helpers with
self.addEventListener()in yoursrc - [ ] Check the browser console: any remaining
[pwa-bundle]warning points at a call you missed - [ ] Set
keep_deprecated_helpers: false - [ ] If you used
self.idbin your own source, switch toindexedDB.open() - [ ] Replace
background_fetchwith your ownbackgroundfetchsuccesshandler - [ ] Declare the caches you open yourself with
registerClearCacheListener() - [ ] Move
favicons.use_start_imagetostartup_images.enabled - [ ] Remove
use_cdnandversionfrom the Workbox configuration, both spellings, and delete the staleworkbox-v7.*folders frompublic/ - [ ] Replace any remaining
Dto\PageCachereference withDto\ResourceCache - [ ] Run
php bin/console pwa:compileand test withAPP_ENV=devto surface the deprecations
Still deprecated (from earlier versions)¶
The following options were deprecated in earlier versions and will also be removed in 2.0.0:
| Option | Replacement | Since |
|---|---|---|
pwa.serviceworker.workbox.use_cdn |
None — remove it, see above | 1.5.0 |
pwa.serviceworker.workbox.version |
None — remove it, see above | 1.5.0 |
pwa.serviceworker.workbox.workbox_public_url |
pwa.serviceworker.workbox.config.workbox_public_url |
1.5.0 |
pwa.favicons.src |
pwa.favicons.default.src |
1.3.0 |
pwa.favicons.src_dark |
pwa.favicons.dark.src |
1.3.0 |
pwa.favicons.background_color |
pwa.favicons.default.background_color |
1.3.0 |
pwa.favicons.background_color_dark |
pwa.favicons.dark.background_color |
1.3.0 |
pwa.favicons.border_radius |
pwa.favicons.default.border_radius |
1.3.0 |
pwa.favicons.image_scale |
pwa.favicons.default.image_scale |
1.3.0 |
pwa.path_type_reference |
URL node path_type_reference parameter |
1.1.0 |