Angular application in custom url path, with ServiceWorker

1.7k views Asked by At

I am developing a Angular 10 application.
It uses the Angular "service worker" to create a PWA.

The compiled application is in "c:\-website-folder-\ng-app\dist". Then the user can access to App with a URL like this: "https://website.com/ng-app/dist".

Configuration of ServiceWorker

Angular ServiceWorker is configured in "app.module":

@NgModule({
    imports: [
        CommonModule,
        BrowserModule,
        ServiceWorkerModule.register(
            `/ng-app/dist/ngsw-worker.js`,
            {
                enabled: true,
                scope: "/ng-app/"
            }
        ),
        ...
    ]
})
export class AppModule {}

The registration ask the path of ServiceWorker.

Project compilation

The Angular project is compiled with ng build command.
It create and fill the "dist" folder. It contains "ng-app.webmanifest" and "ngsw.json".

"ngsw.json" file

The "ngsw.json" file contains a list of all compiled JS and Assets, like GIF, CSS. The Angular ServiceWorker uses this file to cache resources.

{
  "configVersion": 1,
  "timestamp": 1613033261333,
  "index": "/index.html",
  "assetGroups": [
    {
      "name": "app",
      "installMode": "prefetch",
      "updateMode": "prefetch",
      "cacheQueryOptions": {
        "ignoreVary": true
      },
      "urls": [
        "/address-book-editor-address-book-editor-module-es2015.51b00058cbaa9682510e.js",
        "/address-book-editor-address-book-editor-module-es5.51b00058cbaa9682510e.js",
        "/article-editor-article-editor-module-es2015.e4540348b2495fd50875.js",
        "/article-editor-article-editor-module-es5.e4540348b2495fd50875.js",
        "/berry-editor-berry-editor-module-es2015.8cc1850fb1455965c490.js",
        "/berry-editor-berry-editor-module-es5.8cc1850fb1455965c490.js",
        ...
      ],
      "patterns": []
    },
    {
      "name": "assets",
      "installMode": "lazy",
      "updateMode": "prefetch",
      "cacheQueryOptions": {
        "ignoreVary": true
      },
      "urls": [
        "/assets/components/fontawesome/fonts/fontawesome-webfont.eot",
        "/assets/components/fontawesome/fonts/fontawesome-webfont.svg",
        "/assets/components/fontawesome/fonts/fontawesome-webfont.ttf",
        ...
      ],
      "patterns": []
    }
  ],
  "dataGroups": [],
  "hashTable": {
    "/address-book-editor-address-book-editor-module-es2015.51b00058cbaa9682510e.js": "4e6b67457c4b7549f331e6c2cbe3334d13129386",
    "/address-book-editor-address-book-editor-module-es5.51b00058cbaa9682510e.js": "886188af27941dad766bcdcb3e2880b790cf32de",
    "/article-editor-article-editor-module-es2015.e4540348b2495fd50875.js": "985558c2949d9b34d3cdc9e0b7d556d54508b208",
    ...
  },
  "navigationUrls": [
    {
      "positive": true,
      "regex": "^\\/.*$"
    },
    {
      "positive": false,
      "regex": "^\\/(?:.+\\/)?[^/]*\\.[^/]*$"
    },
    {
      "positive": false,
      "regex": "^\\/(?:.+\\/)?[^/]*__[^/]*$"
    },
    {
      "positive": false,
      "regex": "^\\/(?:.+\\/)?[^/]*__[^/]*\\/.*$"
    }
  ]
}

The problem

As you can see, the resources are referenced to ROOT, and Angular ServiceWorker will try to download theese with URL like this

instead of

Help

There is a solution to say to Angular Builder to specify the right URL path?

I am try to change the "ngsw.json" file with right path, and now it works. But it is a Trick...

Thanks very much

1

There are 1 answers

0
mare On

One way to modify paths that Angular generates while building is to use the --deploy-url option with CLI's ng build. In combination with --base-href you can modify paths to some degree but might still get stuck if you use server-side rendering or server-side locales/cultures for instance. But for simple deployment combination of both should work.

That said, unfortunately, only the value of --base-href is included in paths that get generated within the ngsw.json file. This is a problem with Angular CLI and so far hasn't been addressed.

A workaround is to run the ngsw-config command providing it with base href parameter as the last parameter/option.

For example, what you could do is

if your --base-href is /web/ and your --deploy-url is dist/ which when deployed results in your paths being /web/dist/

so for these kinds of paths getting generated correctly in ngsw.json file you'd have to run the following command manually:

./node_modules/.bin/ngsw-config ./dist/ ./ngsw-config.json "/web/dist/"

I went a step further and used npm post scripts (https://michael-kuehnel.de/tooling/2018/03/22/helpers-and-tips-for-npm-run-scripts.html) and configured my package.json like this

...
"build:prod": "ng build --prod --base-href=\"/web/\" --deploy-url=\"dist/\"",
"postbuild:prod": "ngsw-config ./dist/ ./ngsw-config.json \"/web/dist/\"",
...

That way the postbuild:prod always runs after the build:prod cmd.

Hope that helps. I too wish Angular CLI would offer more options for customizing paths in deployed files.