javascriptgoogle-chromeprogressive-web-appsservice-workergoogle-chrome-android

Service worker replacing parts of HTML seemingly has no effect on mobile


I have a service worker on a website:

When user clicks a link on the page (referencing a document on the same host), a script sends a message to the service worker, containing the content of a few elements in the page.

Service worker saves these, intercepts the navigation request, finds these elements in the HTML in response, replaces their content with old content saved from the previous page and returns the modified response.

This is done because the page content is cached as static; and dynamic content in these elements is loaded asynchronously after page load. We want to avoid drawing the elements first with the static content and then redrawing after fetching dynamic content, so we replace it in the intercepted request.

This mostly works on desktop. There is no visible change of content of the dynamic elements.

On mobile (Chrome Android, Chrome iOS), at first glance it seems like it does not work at all. My first guess was the service worker is not running. But after using USB debugging to inspect the page, I see correct log messages from the service worker in the Console and in Network log I can see both the fetch request made by the service worker containing unaltered HTML and the document request made by the page, content already modified by the service worker.

So according to the Dev tools, the service worker is working perfectly. But that's not what you see when interacting with the browser.

How can it be that the page loads modified HTML via the service worker, but displays the unmodified version?


Solution

  • The mobile browser does a lot of speculative prefetching. Since the service worker was setup to act only after a user clicks a link, these prefetch requests are not intercepted and modified. After clicking the link, the browser immediately presents prefetched (unaltered) content, even though another request is sent and intercepted by service worker.