-
Notifications
You must be signed in to change notification settings - Fork 29
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
Implementing forced nullification #25
Conversation
src/modules/core/index.ts
Outdated
// Initialize AMP_SW namespace | ||
self['AMP_SW'] = { | ||
init, | ||
installNoOpServiceWorker, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can really use some help in deciding a better name
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
src/builder/index.ts
Outdated
@@ -23,6 +23,7 @@ export async function buildSW( | |||
documentCachingOptions: {}, | |||
}, | |||
importFrom: string = 'https://cdn.ampproject.org/amp-sw.js', | |||
eject: boolean = false, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's use the same name everywhere, called eject
here and installNoOpServiceWorker
below.
Pick one!
Also, this function could use some documentation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
@@ -32,6 +33,11 @@ export async function buildSW( | |||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
config.offlinePageOptions.assets = (config.offlinePageOptions.assets || []).concat(...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just curious, how is this more readable than what is there today?
} else { | ||
code += `AMP_SW.init(${serializeObject(config || {})})`; | ||
} | ||
|
||
return code; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's move this all to testing directories, since it's purely for test cases.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will do this in a separate PR, issue opened #30
code += 'AMP_SW.installNoOpServiceWorker()'; | ||
} else { | ||
code += `AMP_SW.init(${serializeObject(config || {})})`; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can just return code + ''
instead of conditionals.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
src/modules/core/index.ts
Outdated
declare global { | ||
interface WorkerGlobalScope { | ||
AMP_SW: { | ||
init: Function; | ||
installNoOpServiceWorker: Function; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we add more explicit typing for what the installNoOpServiceWorker
function is?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
src/modules/core/index.ts
Outdated
import(/* webpackChunkName: "service-worker-remover" */ '../service-worker-remover/index').then( | ||
async ({ ServiceWorkerRemover }) => { | ||
const swRemover = new ServiceWorkerRemover(); | ||
swRemover.installNoOpServiceWorker(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not using the value elsewhere, so you can just...
new ServiceWorkerRemover().installNoOpServiceWorker();
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
@@ -0,0 +1 @@ | |||
export const cacheName: string = 'AMP-PREFETCHED-LINKS'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's capitalize this constant, for consistency.
Also, you might consider calling it something more explicit since it's used outside of the link-prefetch
component now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
src/modules/offline-page/index.ts
Outdated
@@ -14,8 +14,8 @@ | |||
* limitations under the License. | |||
*/ | |||
|
|||
import { cacheName as documentCache } from '../document-caching/constants'; | |||
import { cacheName as assetCache } from '../asset-caching/constants'; | |||
import { cacheName as AMP_PUBLISHER_CACHE_NAME } from '../document-caching/constants'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice to avoid the as
statements during import by naming the cacheName
this in the first place. Helps with finding usages.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
src/modules/offline-page/index.ts
Outdated
const publisherCache = await caches.open(documentCache); | ||
const assetsCache = await caches.open(assetCache); | ||
const publisherCache = await caches.open(AMP_PUBLISHER_CACHE_NAME); | ||
const assetsCache = await caches.open(ASSET_CACHE); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like a good place to use Promise.all
or similar, including the fetch in the next line.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
import { cacheName as AMP_PREFETCHED_LINKS } from '../link-prefetch/constants'; | ||
|
||
export class ServiceWorkerRemover { | ||
async installNoOpServiceWorker() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's verify the first version of Safari supporting Service Workers, there is a bug in Safari 10.1 that would preclude an async member from working as expected.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
11.2
export class ServiceWorkerRemover { | ||
async installNoOpServiceWorker() { | ||
// Taking over the document | ||
self.addEventListener('install', function(e: ExtendableEvent) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should these be once
s?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This memory is freed once the service worker is terminated, and post that service worker execution is just event based so i guess this should matter.
Also there is not good place/lifecycle hook to clear these listeners
return clients.claim().then(async () => { | ||
// Cache current document if its AMP. | ||
const windowClients = await clients.matchAll({ type: 'window' }); | ||
windowClients.forEach((client: WindowClient) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
windowClients.forEach((client: WindowClient) => {
client.navigate(client.url);
});
windowClients.forEach((client: WindowClient) => client.navigate(client.url));
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
} | ||
|
||
async cleanCacheStorage() { | ||
return Promise.all([ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we build a test that verifies that an exception thrown in these methods doesn't break the SW?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a bit tough to do in the current e2e test setup due to the following reasons
- The CacheStorage API never rejects the promise it just returns true/false
- The service worker clears the cache and refreshes the window so even if I try to change the prototype to reject the promise, the service worker thread never gets the change.
Instead I can test this with a unit test case instead.
I'll setup a unit test setup and add a unit tests around service worker forced nullification
in a separate PR.
It also makes sense to have these tests for forced nullification
module because this piece is beyond just configuring workbox
|
||
it('should remove currently registered service worker', async () => { | ||
const installedServiceWorker = await driver.executeAsyncScript(async cb => { | ||
executeScript(async cb => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
executeScript(async cb => {
cb(navigator.serviceWorker.controller.scriptURL);
}, cb);
executeScript(async cb => cb(navigator.serviceWorker.controller.scriptURL), cb);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See comments.
src/modules/core/index.ts
Outdated
@@ -96,7 +98,16 @@ function init(config: ServiceWorkerConfiguration = {}) { | |||
}); | |||
} | |||
|
|||
function forcedNullifcation() { | |||
import(/* webpackChunkName: "service-worker-remover" */ '../service-worker-remover/index').then( | |||
async ({ ServiceWorkerRemover }) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
async ({ ServiceWorkerRemover }) => {
new ServiceWorkerRemover().installNoOpServiceWorker();
},
Can be rewritten as...
async ({ ServiceWorkerRemover }) => new ServiceWorkerRemover().installNoOpServiceWorker(),
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
are you aware of a prettier rule for this?
This definitely looks like an optimization that should either be done by prettier or the compiler.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
manually fixing this for now
installNoOpServiceWorker
which removes the currently installed service worker.amp-sw
caches