41

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/**"
          ]
        }
      }]
    }
Luca Ritossa
  • 1,118
  • 11
  • 22
ktretyak
  • 27,251
  • 11
  • 40
  • 63
  • So If I am not wrong you want to use the route `/api/rss` which points to some other place not any URL or pageview from your angular app and service worker should not load anything from that URL – Panna Das Dec 13 '17 at 12:55
  • @PannaDas, Angular application should not serve this URL. – ktretyak Dec 14 '17 at 13:52

7 Answers7

44

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/**"
        ]
      }
    }
  ]
}
Florian
  • 2,796
  • 1
  • 15
  • 25
ktretyak
  • 27,251
  • 11
  • 40
  • 63
  • 2
    Everything I put in Datagroups seems ignored. I don't have the datagroup in the ngsw.json file generated in dist (with ng build --prod). Do you have it with this configuration or is it working an other way ? – switch Dec 29 '17 at 18:56
  • 1
    This works only to GET requests. We are having a problem when a file progress bar doesn't work because of SW. We did the solution that is suggested here: https://github.com/angular/angular/issues/21191#issuecomment-360051276 until Angular will add a native support for that – doron Jan 25 '18 at 08:38
  • 4
    Does it works for the external urls as well(i.e for cdn files)? I am trying but doesn't work for me – Borad Akash Mar 12 '19 at 14:32
  • This way is not working from my side; just the way bypassing URLs from angular service workers by using ngsw-bypass from https://stackoverflow.com/a/58520498/1979190 is working. – Tang Thanh Tam Aug 21 '23 at 02:26
22

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";
    }
  }]
}
Pedro Arantes
  • 5,113
  • 5
  • 25
  • 60
21

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

ChrisOdney
  • 6,066
  • 10
  • 38
  • 48
  • 2
    This is definitely a better answer than the accepted one. This because now you don't have to edit the ngsw-config.json-file, which I assume is best to leave alone (if possible) for easier future updates. – Ramo Mislimi Nov 30 '20 at 09:28
  • this is not working for me, it gets fully ignored the ngsw-bypass param and the ngsw-bypass header as well – sgClaudia98 Feb 24 '22 at 02:33
13

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.

Johan Faerch
  • 1,109
  • 4
  • 13
  • 31
  • 2
    I think your solution is the best! But you also need to include the default navigationUrls from the doc: `"navigationUrls": [ "/**", "!/**/*.*", "!/**/*__*", "!/**/*__*/**", "!/api/rss"`] – illnr Dec 14 '20 at 16:52
  • I did try this, and it's not working. One of my navigationUrls is `"!/web/v3/Account/connect/**/**"`, and the url `/web/v3/Account/connect/web/microsoft` is still opening in the PWA when using `window.open()` – Pieterjan Jul 25 '21 at 11:07
  • @Pieterjan did you find solution for this? – sgClaudia98 Feb 24 '22 at 02:34
  • Yes, by opening the new window using a subdomain. Next you'll need to alter the cookie domain to include this `external.example.com` so that `ExternalLoginSigninAsync` signs you in for the base domain (too) – Pieterjan Feb 24 '22 at 07:07
  • In case a subdomain isn't an option for you, [here's the bugtracker issue](https://bugs.chromium.org/p/chromium/issues/detail?id=1236536&q=&can=4) – Pieterjan Feb 24 '22 at 07:10
  • + the `TwoFactorSigninAsync` most likely needs to be called from the same domain, so if you're signing in through eg Microsoft, you'll need to navigate to an MVC view to ask for the 2FA code – Pieterjan Feb 24 '22 at 07:23
  • This way is not working from my side; just the way bypassing URLs from angular service workers by using ngsw-bypass from https://stackoverflow.com/a/58520498/1979190 is working. – Tang Thanh Tam Aug 21 '23 at 02:26
4

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.

Trent
  • 4,208
  • 5
  • 24
  • 46
0

In the ngsw-config.json file

{
  "index": "/index.html",
  "dataGroups":
  [
    {
      "name": "api",
      "urls": ["!/**/*profileimageupload*"],
      "cacheConfig": {
        "maxSize": 0,
        "maxAge": "0u",
        "strategy": "freshness"
      }
    }
  ]  
}

eg. If your API is like https://api.example.com/profileimageupload/ then add last segment from the Service/API

I add profileimageupload which I want to Exclude(remove) calling from service worker that's why I added !/**/yourService/Api last name,

msanford
  • 11,803
  • 11
  • 66
  • 93
Sachin from Pune
  • 656
  • 8
  • 19
  • https://angular.io/guide/service-worker-config#urls : Negative glob patterns are not supported. – Remco Jan 17 '22 at 10:40
0

you can disable service worker for specific request, via headers or query string.

More Detail;

Go github issue please

smith
  • 1