Skip to content

Add ability to set URL for ngsw.json at runtime #51457

Description

@anhallbe

Which @angular/* package(s) are relevant/related to the feature request?

service-worker

Description

TL;DR: We cannot serve ngsw-worker.js and ngsw.json from the same origin, so we'd like a way to configure where ngsw.json is fetched from.

Our setup requires us to serve the application (i.e files produced by ng build) from an external CDN. The CDN URL and path cannot be known at build-time, and is set by the server when the index file is rendered (e.g with Thymeleaf). Think:

// index.html
<script>
  window.APP_CONFIG = {
    cdnUrl: [[${CDN_URL}]]
  };
</script>

<script th:src="@{${CDN_URL}+'polyfills.js'}"></script>
<script th:src="@{${CDN_URL}+'runtime.js'}"></script>
<script th:src="@{${CDN_URL}+'main.js'}"></script>

When trying to add @angular/service-worker for offline support into the mix, we run into the issue that the ngsw-worker.js script cannot be served from the CDN like other files, because of browser restrictions.

We can work around this by having the ngsw-worker.js be served from the page origin. However, we'd still like for the ngsw.json manifest to be served together with the rest of the app from the CDN. And this is the issue. There is no way to tell the service worker to fetch the manifest from a different path/url.

Proposed solution

Add a runtime config property that allows to override the default ngsw.json path. For example:

ServiceWorkerModule.register("ngsw-worker.js", {
	// ...
	manifestUrl: `${window.APP_CONFIG.CDN_URL}/ngsw.json`,
}),

Note that for our setup, the CDN URL is not known at build-time, so it cannot be a part of ngsw-config.json.

EDIT:
Another possible solution would be something like:

ServiceWorkerModule.register("ngsw-worker.js", {
	// ...
	ngswOrigin: "sw-scope" | "import-meta",
}),

...where "sw-scope" would be default (and the way it works right now), and "import-meta" would become a URL that is based on where the main.js script is loaded from. Possibly based on import.meta.url.

EDIT2:
I forgot to add: If the ngsw.json is served from an external URL, then there must also be a way to tell the service worker that the URL:s inside of it are relative. Like so:

// https://the.cdn/path/to/ngsw.json
{
  "assetGroups": [
    {
      "urls": [
          "main.js" // Service Worker should interpret this as https://the.cdn/path/to/main.js
        ],
    }
  ],
}

Alternatives considered

One alternative we tried was to serve ngsw.json from the page origin (i.e the same as ngsw-worker.json).

However this is not ideal, as the CDN files are deployed more or less independently from the index page.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    area: service-workerIssues related to the @angular/service-worker package

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions