Skip to content

Service worker responds slowly (10 seconds) when many query parameters are present #3077

Closed

Description

@westonruter

Library Affected:
workbox-strategies

Browser & Platform:
Google Chrome v101.0.4951.41

Issue or Feature Request Description:

On a site using the PWA plugin for WordPress, which includes Workbox, the service worker is taking 10 seconds for the NetworkFirst strategy to respond to requests for URLs that have many query parameters.

Steps to reproduce:

  1. Go to https://www.sensorsone.com/ and let the service worker install
  2. Try reloading the page and see it only takes a couple seconds.
  3. Now try going to the same URL with many query parameters, and notice that the response from the service worker takes over 10 seconds.
  4. Now in the Application tab of DevTools, enable "Bypass for Network" and reload the same URL with many query parameters. Now the response is returned relatively quickly as in the first step.

Originally reported on the WordPress plugin support forum

Activity

  1. changed the title [-]Service worker responds slowly (1)[/-] on May 5, 2022
  2. westonruter commented on May 5, 2022

    @westonruter
    ContributorAuthor

    I just saw that the user was running PWA plugin v0.6 which included Workbox v5. I'm asking them to update to v0.7 which includes the current Workbox version to see if that fixes the issue.

  3. jeffposnick commented on May 5, 2022

    @jeffposnick
    Contributor

    This is due to the denylist functionality in the service worker's navigation routing:

    Screen Shot 2022-05-05 at 4 42 38 PM

    The following RegExps are each being tested against the long pathname + search:

    1. /^\/wp\-admin($|\?.*|\/.*)/
    2. /[^\?]*.\.php($|\?.*)/
    3. /.*\?(.*&)?(wp_service_worker)=/
    4. /.*\/wp\.serviceworker(\?.*)?$/
    5. /[^\?]*\/feed\/(\w+\/)?$/
    6. /\?(.+&)*wp_customize=/
    7. /\?(.+&)*customize_changeset_uuid=/
    8. /^\/wp\-json\/.*/

    I can't tell you offhand which one of them is giving you particularly bad performance when tested against that long input, but it normally tends to be a RegExp that does a bunch of backtracking. You could try removing them one by one from your denylist until you find the one(s) that are expensive, and then attempt to optimize it.

    I'm going to close this issue, since it appears to be more about how Workbox is configured than about the core functionality. Let me know if there's anything else I can do to assist, though.

  4. added and removed
    Needs More InfoWaiting on additional information from the community.
    on May 5, 2022
  5. jeffposnick commented on May 5, 2022

    @jeffposnick
    Contributor

    ...one more thing is that if you really need to keep the current set of RegExps in your denylist, but you want them matched against just the pathname portion of the URL, you could do that pretty easily via a custom matchCallback:

    const denylist = [/.../, /.../];
    const navigationMatcher = ({request, url}) => {
      if (request.mode !== 'navigate') {
        return false;
      }
      for const (regexp of denylist) {
        if (regexp.test(url.pathname)) {
          return false;
        }
      }
      return true;
    };
    
    registerRoute(
      navigationMatcher,
      SomeStrategy(),
    );

    This would help if you know that it's unlikely for folks to have a very long path, while it's more likely for them to have a lot of query parameters.

    You could also get more fine-grained to how you match your path segments while avoiding RegExps if you need to:

    const skipIfSegmentMatches = ['skip1', 'skip2'];
    const navigationMatcher = ({request, url}) => {
      if (request.mode !== 'navigate') {
        return false;
      }
      const segments = url.pathname.split('/');
      for const (segment of skipIfSegmentMatches) {
        if (segments.includes(segment)) {
          return false;
        }
      }
      return true;
    };
    
    registerRoute(
      navigationMatcher,
      SomeStrategy(),
    );
  6. westonruter commented on May 6, 2022

    @westonruter
    ContributorAuthor

    Thanks a lot! I was able to identify these two patterns as causing the expensive backtracing:

    /\?(.+&)*wp_customize=/
    /\?(.+&)*customize_changeset_uuid=/
    

    I'm going to optimize those and then consider your improved denial logic for the future.

    🙇

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions