-
Notifications
You must be signed in to change notification settings - Fork 829
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
Issue with cacheDidUpdate plugin in workbox-precaching when other callbacks are also used #2878
Comments
Can you try it with
A plugin is an object that has callback functions with properties like Hopefully that works. Otherwise, we can reopen the issue./ |
I'm sorry - it was my typo here - in fact, my code is as follows const myPlugins = {
handlerDidError,
cacheDidUpdate
};
addPlugins([myPlugins]); but the result is the same |
I've found the problem: addPlugins([
{cacheDidUpdate},
]); Everything works as expected addPlugins([{
cacheDidUpdate,
handlerDidError,
cachedResponseWillBeUsed,
}]); cacheDidUpdate doesnt work Here is the code of the other plugins export const handlerDidError = ({ request }) => {
logError(request);
return null;
};
export const cachedResponseWillBeUsed = async ({ cacheName, request, cachedResponse }) => {
if (cachedResponse) {
return cachedResponse;
}
const cache = await caches.open(cacheName);
const response = await fetch(request);
if (!response.ok) {
logError(request, 'Error loading asset');
return null;
}
await cache.put(request, response.clone());
return response;
}; |
Hmmm... let me look into that more closely, as in general, you should be able to use various plugin callbacks together. I'm glad you have a workaround for the time being, though. |
I'm revisiting this, and just to clarify, are you saying that If you mean the latter, then that's excepted, as |
if I use both plugins:
but I need both of them and to have an ability to watch for installation progress and an ability to "repair" app cache |
I'm still unclear on exactly what's going on. Taking a step back, #2858 tracks another request to "repair" precached assets outside of the normal service worker lifecycle. If we added that functionality in an upcoming release (but only for precache manifest entries that had an |
See #2921 for the proposed "repair" logic. |
This would definitely help us get rid of our "recovery" plugin! |
Okay, that PR should be included in the |
The precaching repair functionality is now live in https://github.com/GoogleChrome/workbox/releases/tag/v6.3.0 |
Thanks! |
@jeffposnick This is not a static element - it's dynamically generated depending on the browser, for each client, and depending on many other parameters - so it is not possible to use |
I don't feel comfortable adding in automatic precache repair functionality unless If I had a dynamically generated HTML page that was heavily customized for each client, I don't think I would use precaching for that to begin with, though, since it's probably very difficult to generate a meaningful hash of the contents at build time. Using a
|
This solves the problem, but breaks the uniformity and simplicity - a developer will have to be informed about this case and should not forget to exclude the ` / ' route from the manifest and add the code to the worker service. The solution with integrity, it seems to me, complicates the process - it forces us to write additional code for generating hash (this can be solved by an option in the config, and by the code in the library), although we have either revision or its hash / version is contained in the resource name itself in the manifest My opinion about restoring pre-cache elements is that they can and should be re-requested uniformly without writing a code and all the information for this is already in the manifest. |
All of the Workbox tools that are used to generate a manifest, by default, will look at actual assets on disk (or in a
To repeat what I mentioned above—I think the fundamental issue is that you shouldn't have CC: @malchata, who is working on revamping our docs, in case this is something that we can clarify there. |
Why not ? I'm sorry, but I don't understand why we can't have I agree that it is not static and generating a revision for it does not make sense, but it is possible that there may be several such resources in the project and it is possible to add a flag to the manifest configuration that this is a dynamic resource and it just needs to be loaded If we had an option in the workbox configuration that the resource is dynamic , there would be no need to generate integrity property (and how about the idea of putting integrity generation (if it is still needed) under the hood of the workbox if there is a flag in the configuration?) |
It's just that Workbox's solution for caching dynamic resources is to use a runtime route to handle serving what's already in the cache and updating it with the most appropriate strategy based on your knowledge of your architecture. It might be stale-while-revalidate, or network-first, or something else. If you need to guarantee that the resource is in the cache during service worker installation, writing a custom If you're asking about how to configure our build tools to generate this sort of runtime caching route, you can do that with the |
The library should simplify the life of a developer. The simplicity of its use lies in a simple declaration of what he would like to pre-cache - and this is a simple list of resources. Considering your suggestions and objections, the developer should be very well versed in the nuances of the library when working with static and dynamic resources in precache list, although he does not need it and complicates the use of the library. I apologize if my statements are harsh, but I think like a library user and in this form I see chaos: in one place I have to use the library with it's declarations, and in other places I have to write native code for the implementation of the service worker. So isn't it easier then to write everything with hands? the ' / ' route is one of the elements of the precache list - why should I process it separately from the other elements of this list? This only complicates the use of the library and introduces confusion
I'm talking about writing by hands integrityManifestTransform for generating integrity property - it should be automated with workbox with an option in config |
Thanks for continuing to engage with us here—I do want to figure out exactly how you've approached Workbox, and learn from that had we could better guide folks towards better outcomes in our documentation (or add in new features when appropropriate).
So I wanted to push back a bit here, because while you're able to pass in whatever list of precache entries you want to Based on what you're describing, there's an entry for
That's a fair point, and the custom import {warmStrategyCache} from 'workbox-recipes';
import {registerRoute} from 'workbox-routing';
import {StaleWhileRevalidate} from 'workbox-strategies';
const indexStrategy = new StaleWhileRevalidate({cacheName: INDEX_CACHE});
registerRoute(
({url}) => url.pathname === '/',
indexStrategy
);
warmStrategyCache({
strategy: indexStrategy,
urls: ['/'],
});
This goes back to my earlier point, since the same complication around generating a |
Ok, I'll tell you how our service worker is arranged and how we would like it: we generate the manifest using the InjectManifest plugin. const updatedManifest = [
...self.__WB_MANIFEST,
{
url: '/',
revision: packageJson.version,
},
]; Webpack generates us resource names with contenthash. This is quite enough to have a consistent precashe for offline. Given that other developers may not have the contenthash, you suggest generating an integrity attribute for them. new InjectManifest({
swSrc: '...',
swDest: 'sw.js',
...
generateIntegrityAttribute: true
}), a dynamically generated resources (resources without the integrity attribute) I would upload it as it is - they do not require any verification. Now I hope everything is clear and transparent, and when" repairing" the damaged precache, you can safely download all the resources specified in the manifest. |
Thanks for sharing that. I think we'll add in an Getting back to your specific usage, apart from all other aspects of this discussion, I would recommend that you don't add any entries to the precache manifest that is generated by the build tools unless you're sure that the I am at a loss for how the Workbox libraries could prevent you from doing what you're doing, so I don't think that this is a problem that could just be solved by improving the developer experience. We currently have warnings enabled if you just manually added an entry with a workbox/packages/workbox-precaching/src/PrecacheController.ts Lines 158 to 169 in 03055e6
|
This approach greatly complicates the life of the developer and disorients beginners - static resources and a If I were developing a workbox, I would implement such a contract new InjectManifest({
swSrc: '...',
swDest: 'sw.js',
include: [
{
url: '/?source=pwa', // static resource is generated by server
revision: <revision>,
},
{
url: '/anotherStaticResourceFromServer',
revision: <revision>,
},
{ url: '*.(js|json)' },
{ url: '*.css' },
],
addIntegrity: true
}), And under the hood I would get the integrity attribute for static resources and for static resources from server (with revision) I would do nothing - simply put them as is into manifest assets array. Thus, the developer would only have to focus on working with the rest of the resources that are not included in the precache list. P.S: I want to emphasize once again that in this case for example, '/?source=pwa' route - is an app-shell for the pwa, which is rendered by the server at the request of the client from components that are build and tested during the build process |
@jeffposnick Maybe we should make something like precache routes or runtime precache to cover SSR cases like this. I've got similar questions from the community guys who implement PWA in SSR. |
To summarize all of the above - we have two types of precache assets in SSR
|
@jeffposnick This is a question about DX (developer experience). From what I can see currently Workbox is more focused on CSR (client-side rendering) PWA. In CSR PWA the app shell are always files. And these files are static and always available at build time (at service worker generation time). You can easily calculate file checksums (hashes/revisions). And these app shell files are identical for all users. SSR PWA is a different story. Some of app shell files can be generated in runtime and be different for various users. But they are still a part of app shell. And should be precached (like the rest of static files). The content of these files is unavailable at build time, so you can't calculate checksums. All that developer know is URL. And as far as I understand, Workbox doesn't actually validate (recalculate) the checksum of files from cache. Right? The current goal of If so, I like the idea of allowing declaring dynamic routes in the |
In other words, the idea is to declare all the things should be precached in one single place — in |
UPD: you can use optional |
The issue with the declaration of resources from the server in new InjectManifest({
swSrc: '...',
swDest: 'sw.js',
include: [
{ url: '*.(js|json)' },
{ url: '*.css' },
],
additionalManifestEntries: [
{
url: '/?source=pwa',
revision: <revision>,
},
{
url: '/anotherStaticResourceFromServer',
revision: <revision>,
},
],
addIntegrity: true
}), There is no need to change anything - the plugin parameters have all the possibilities for flexible description of all types of resources @FluorescentHallucinogen , thank you for your help in solving the issue |
I think we need to improve Workbox docs by adding samples for |
Hey all—the existence of the const moreEntries = [
{url: '/?source=pwa', revision: '<somethingHardcoded>'},
{url: '/anotherStaticResourceFromServer', revision: '<somethingElseHardcoded>'},
];
precacheAndRoute([...self.__WB_MANIFEST, ...moreEntries]); in your It is really not a good idea to precache any URL whose content might change outside of your build process, i.e. any HTML that's server-rendered. I've done my best to explain upthread why this is the case, and why runtime caching is the right approach. But to summarize, the logic and data sources that your server uses to generate that SSR response may change, and the initially precached entries won't end up updated, because the I'm sorry that the DX might feel a bit different than what you'd prefer, and there is likely some ability to extend the options in our Finding the right way to explain this nuance in our documentation is definitely a challenge, and again, I apologize that this is not currently clearer. @malchata continues to work on a revamp of all of our existing documentation, and this discussion has informed some of the guidance he'll be writing. In the meantime, here are some less formal thoughts that I've written up on precaching vs. runtime caching, and one approach to coordinating SSR logic with service worker code. |
I'm sorry, but you misunderstand the purpose of We use it as navigation route registerRoute(
new NavigationRoute(createHandlerBoundToURL('/?source=pwa')),
); revision - in our case, not hardcoded, but the version of the application on which the server rendering of this resource depends |
Hello @budarin—if you have a mechanism in place to ensure that the (Going back to what the original question was about, the precaching "repair" can't be handled by Workbox unless there's also an |
Unfortunately, it is not possible to get the integrity value at the build stage. now the process for tasks that used to be simple has become very complicated - what I used to do without even thinking about it now looks either very difficult or not possible :( PS: I believe that using integrity checks during repair should be used only when the |
In the interest of closing out this issue, I've revisited the original complaint, which is that when you add your I went through a reproduction steps, and identified the following issue: your During the In other words, your code should change to: const cachedResponseWillBeUsed = async ({cacheName, request, cachedResponse, event}) => {
// Return early if cachedResponse is already set, or if this is an install event,
// where cachedResponse being undefined is not an error.
if (cachedResponse || event.type === 'install') {
return cachedResponse;
}
// Your "cache repair" code goes here.
} Hopefully this change in your I don't have much more to add beyond what I've already mentioned upthread regarding the other topics. |
@jeffposnick thanks! |
(I've updated the code sample to use |
In my application, I display a splash screen and wait for complete the installation of the service worker and only then display the content, because the service worker must manipulate the csp token for several tabs for all requests in the API.
On a slow connection, the installation of a service worker can take up to a minute. I would like to keep the user busy with the progress of caching elements at this time.
I read #2406 and wrote a custom plugin for cacheDidUpdate:
I used it in the service worker
but I didn't see anything in the console.
What am I doing wrong?
The text was updated successfully, but these errors were encountered: