Skip to content

bug(ServiceWorker): multiple apps with ServiceWorker on one domain #21388

Closed
@skydever

Description

@skydever

I'm submitting a...


[ ] Regression (a behavior that used to work and stopped working in a new release)
[x] Bug report  
[ ] Feature request
[ ] Documentation issue or request
[ ] Support request => Please do not submit support request here, instead see https://github.com/angular/angular/blob/master/CONTRIBUTING.md#question

Current behavior

The installation of a 2nd App/ServiceWorker (with different baseHref) purges the Cache Storage entries for a previously installed App/ServiceWorker, if they are on the same domain. This breaks the 1st installed App. It is not reachable anymore - you will always be redirected to the latest installed App.

Expected behavior

The installation of multiple Apps/ServiceWorkers (with different baseHref) on one domain should be possible.

Minimal reproduction of the problem with instructions

I created the following repo to reproduce the issue: https://github.com/skydever/repro-multiple-ng-apps-one-domain-serviceworker. Follow the steps of the README there.

What is the motivation / use case for changing the behavior?

I have to deploy multiple Angular Apps on one domain.

Environment


Angular version: 5.1.3


Browser:
- [x] Chrome (desktop) version XX
- [ ] Chrome (Android) version XX
- [ ] Chrome (iOS) version XX
- [ ] Firefox version XX
- [ ] Safari (desktop) version XX
- [ ] Safari (iOS) version XX
- [ ] IE version XX
- [ ] Edge version XX
 
For Tooling issues:
- Node version: v8.9.1  
- Platform: Windows 

Others:

Activity

skydever

skydever commented on Jan 12, 2018

@skydever
Author

@alxhub Could this be a valid solution at db-cache.ts?

export class CacheDatabase implements Database {
  private cacheScope: String; // to distinct between multiple scopes
  private tables = new Map<string, Promise<CacheTable>>();

  constructor(
    private scope: ServiceWorkerGlobalScope,
    private adapter: Adapter
  ) {
    this.cacheScope = this.scope.scope !== './' ? `:${this.scope.scope}` : '';
  }

  delete(name: string): Promise<boolean> {
    if (this.tables.has(name)) {
      this.tables.delete(name);
    }
    return this.scope.caches.delete(`ngsw:db${this.cacheScope}:${name}`);
  }

  list(): Promise<string[]> {
    return this.scope.caches
      .keys()
      .then(keys =>
        keys.filter(key => key.startsWith(`ngsw:db${this.cacheScope}:`))
      );
  }

  open(name: string): Promise<Table> {
    if (!this.tables.has(name)) {
      const table = this.scope.caches
        .open(`ngsw:db${this.cacheScope}:${name}`)
        .then(cache => new CacheTable(name, cache, this.adapter));
      this.tables.set(name, table);
    }
    return this.tables.get(name)!;
  }
}

... but I have to provide different scopes, and the scope will always be ./ by default (and wanted so to intercept all requests down the url path where the service worker script is located) ... maybe get the baseHref somehow? but how can I obtain it safely not doing something like document.getElementsByTagName('base')[0].href?

skydever

skydever commented on Jan 13, 2018

@skydever
Author

found this at browser_adapter.ts:

let baseElement: HTMLElement|null = null;
function getBaseElementHref(): string|null {
  if (!baseElement) {
    baseElement = document.querySelector('base') !;
    if (!baseElement) {
      return null;
    }
  }
  return baseElement.getAttribute('href');
}

it is related to the platform that is used and I don't know how to wire this up ...

skydever

skydever commented on Jan 13, 2018

@skydever
Author

just get it in a safe way using document if available, sw are only available in the platform browser ...

skydever

skydever commented on Jan 14, 2018

@skydever
Author

the CacheDatabase is service worker code, so no dom access there ... I can manipulate the ngsw-worker.js after the build process to include the app/baseHref info in CacheDatabase, by replacing the 3 ngsw:db: entries with ngsw:db:[app-base-href]: ...

skydever

skydever commented on Jan 17, 2018

@skydever
Author

I created an issue at the Angular CLI repo too. both are involved somehow, the baseHref option of the CLI needs to be passed to the service worker. I don't think that the service worker is able to do that without information from the CLI?

added this to the Backlog milestone on Jan 23, 2018
skydever

skydever commented on Jan 24, 2018

@skydever
Author

replacing the ngsw:db: key seems not to work (even replacing the 6 occurences of ngsw: with a unique key does not work, but the distinction is better if you look at the Cache Storage at the dev tools - there are some entries without the ngsw:db prefix if you just replace the 3 occurences of ngsw:db) - the content of the control entry in the CacheDatabase still gets overwritten from another app ...

skydever

skydever commented on Jan 26, 2018

@skydever
Author

did some more research, maybe this is helpful somehow. after renaming ngsw: (6 entries in ngsw-worker.js) to ngsw:swAppOne and ngsw:swAppTwo it seems to work, but the Cache Storage seems like to be in an invalid state ... I created a branch in my repo for that, just npm install in sw-app-one and run npm run start-sw and open the pages at sw-app-one and sw-app-two, then have a look into the Cache Storage in the dev tools - the entries ngsw:sw-app-two:db:control and ngsw:sw-app-one:db:control have the same values for assignments, latest and manifests - an image of it here.

Afterwards I also renamed the entries assigments to assigmentsSwAppOne and so on (the other way round in the commit, was to create a reproduction of the weird state). The result looks clean now, with all the renaming. but still weird somehow, I also refreshed the cache in the dev tools ...

46 remaining items

Loading
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

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @Splaktar@kara@alxhub@canhamd@gkalpak

        Issue actions

          bug(ServiceWorker): multiple apps with ServiceWorker on one domain · Issue #21388 · angular/angular