Angular 5 and Service Worker: How to exclude a particular path from ngsw-config.json

19,617

Solution 1

Thanks to the Pedro Arantes advice, I reached the next working config (see dataGroups and "maxAge": "0u"):

{
  "index": "/index.html",
  "dataGroups":
  [
    {
      "name": "api",
      "urls": ["/api"],
      "cacheConfig": {
        "maxSize": 0,
        "maxAge": "0u",
        "strategy": "freshness"
      }
    }
  ],
  "assetGroups":
  [
    {
      "name": "app",
      "installMode": "prefetch",
      "resources": {
        "files": [
          "/favicon.ico",
          "/index.html"
        ],
        "versionedFiles": [
          "/*.bundle.css",
          "/*.bundle.js",
          "/*.chunk.js"
        ]
      }
    },
    {
      "name": "assets",
      "installMode": "lazy",
      "updateMode": "prefetch",
      "resources": {
        "files": [
          "/assets/**"
        ]
      }
    }
  ]
}

Solution 2

Have you already tried to create data groups? dataGroups are used to data request such as assetGroups to assets (which are files).

Data Groups

Unlike asset resources, data requests are not versioned along with the app. They're cached according to manually-configured policies that are more useful for situations such as API requests and other data dependencies.

Data Group interface:

export interface DataGroup {
  name: string;
  urls: string[];
  version?: number;
  cacheConfig: {
    maxSize: number;
    maxAge: string;
    timeout?: string;
    strategy?: 'freshness' | 'performance';
  };
}

You might create a data group that excludes /api/rss (if "!/api/rss" does not work, you can add all others APIs in urls": ["/api/user", "/api/admin"]:

{
  "index": "/index.html",
  "assetGroups": [{
    "name": "assetGroup1",
    ...
  }, {
    "name": "assetGroup1",
    ...
  }],
  "dataGroups": [{
    "name": "dataGroup1";
    "urls": ["!/api/rss"];
    cacheConfig: {
      maxSize: 50;
      maxAge: "3d12h";
    }
  }, {
    "name": "dataGroup2";
    "urls": ["/api/user"];
    cacheConfig: {
      maxSize: 40;
      maxAge: "3d12h";
    }
  }]
}

Solution 3

This has been made easier now, you can bypass URLs from angular service workers by using ngsw-bypass. From the docs:

To bypass the service worker you can set ngsw-bypass as a request header, or as a query parameter. (The value of the header or query parameter is ignored and can be empty or omitted.)

I am using the query string to bypass a certain url from service worker like this:

https://mydomain.report-uri.com/r/d/csp/enforce?ngsw-bypass=true

Solution 4

The correct way of doing this is to omit the endpoints from the index redirect. So your ngsw-config.json should look like this with added navigationUrls and negation of the url part you wish to omit. This way the URL will just be redirected and circumvent the ngSW entirely.

    {
      "index": "/index.html",
      "assetGroups": [{
        "name": "app",
        "installMode": "prefetch",
        "resources": {
          "files": [
            "/favicon.ico",
            "/index.html"
          ],
          "versionedFiles": [
            "/*.bundle.css",
            "/*.bundle.js",
            "/*.chunk.js"
          ]
        }
      }, {
        "name": "assets",
        "installMode": "lazy",
        "updateMode": "prefetch",
        "resources": {
          "files": [
            "/assets/**"
          ]
        }
      }],
      "navigationUrls": [
        "!/api/rss"
      ]
    }

Note that !/api/rss is specific. If you want to omit the entire api folder use !/api/** instead.

Documentation here https://angular.io/guide/service-worker-config#navigationurls

Please note that negating (!) does NOT work under "resources": "urls": according to the docs.

Solution 5

The ngsw-configuration.json file uses glob format for pattern matching paths.

Patterns use a limited glob format:

** matches 0 or more path segments.
* matches exactly one path segment or filename segment.
The ! prefix marks the pattern as being negative, meaning that only files that don't match the pattern will be included.

What is important here is the ! prefix, which can be used to exclude a path. For example, a glob pattern of !/api/rss should exclude this path.

To exclude a path from your nags-configuration.json file, simply prepend the ! character to this path pattern.

Share:
19,617
ktretyak
Author by

ktretyak

Updated on June 03, 2022

Comments

  • ktretyak
    ktretyak almost 2 years

    I have ngsw-config.json (taken from the docs):

        {
          "index": "/index.html",
          "assetGroups": [{
            "name": "app",
            "installMode": "prefetch",
            "resources": {
              "files": [
                "/favicon.ico",
                "/index.html"
              ],
              "versionedFiles": [
                "/*.bundle.css",
                "/*.bundle.js",
                "/*.chunk.js"
              ]
            }
          }, {
            "name": "assets",
            "installMode": "lazy",
            "updateMode": "prefetch",
            "resources": {
              "files": [
                "/assets/**"
              ]
            }
          }]
        }
    

    On my site there is a link to the RSS feed /api/rss, which should open in a new browser tab without loading Angular app. How can I exclude it from a list of resources whose request is redirected to index.html?

    UPD: I tried but not working the following config (see !/api/rss):

        {
          "index": "/index.html",
          "assetGroups": [{
            "name": "app",
            "installMode": "prefetch",
            "patterns": ["!/api/rss"],
            "resources": {
              "files": [
                "/favicon.ico",
                "/index.html",
                "!/api/rss"
              ],
              "versionedFiles": [
                "/*.bundle.css",
                "/*.bundle.js",
                "/*.chunk.js"
              ]
            }
          }, {
            "name": "assets",
            "installMode": "lazy",
            "updateMode": "prefetch",
            "resources": {
              "files": [
                "/assets/**"
              ]
            }
          }]
        }