Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 5 Multiple Service Worker in one domain

I have two service workers in two application on the same domain (both Angular 5):

  • one inside /frontend/
  • second inside /backend/

I am using @angular/service-worker package to manage service worker.

When i build prod version and deploy my applications something strange happens.

When im enter first to http://my.domain/frontend/ i can't go to http://my.domain/backend/ because service worker loading files and redirect me to http://my.domain/frontend/

What is wrong with this setup? i need to change file name of that service worker, or just i can't have two angular application on the same domain with this setup

like image 554
pr0metheus Avatar asked Dec 21 '17 14:12

pr0metheus


2 Answers

I had the same issue (after restarting the browser, server down - just got data from the ServiceWorker as expected, but mixed up). Then I came across this stackoverflow question and changed the names of the assetGroups to distinct names between all (2 in my case for now) apps.

eg:

ngws-config.json from App 1:

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

ngws-config.json from App 2:

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

because of:

The Cache Storage API (and other storage mechanisms, like IndexedDB) are shared throughout the entire origin, and by default there's no "sharding" or namespace segregation.

My guess is that this default names are used in the Cache Storage for both apps (but there is also a hash, that is what still confuses me). I also checked the Cache Storage and deleted all ngsw:* entries not containig sw-app (or sw-app-two).

After these changes everything seemed to work better but then after some reloads (with active server) I realised that my sw-app entries from the Cache Storage where gone after opening sw-app-two. There were only sw-app-two entries and one entry named ngsw:db:control left. This entry only contained the assetGroups of the sw-app-two's ngsw-conig.json (under manifest). After opening sw-app again, the content in the manifest for the assetGroups changed to sw-app and the sw-app-two content was gone.

So I have ngsw:db:control left with sw-app content, and the other Cache Storage entry names contain sw-app-two. When I open both apps (server down) there is always sw-app-two coming up (without errors, but it is just an app without real content). This mixup works for one app, also confusing somehow.

Some more details, but still no solution. Would love to check the angular code and make a PR but .... at least file an issue. I am quite sure the Cache Storage gets mixed up between apps under the same origin.

PS: When you set the baseHref be sure to check this github issues too: #8515 #8516

EDIT: I created issue #21388

EDIT(2):

Service Worker scripts must be hosted at the same origin (Protocol + Domain name + Port). mentioned at this stackoverflow question

I will create a sub-domain for each app and run multiple http servers on different ports locally to test it. This should work and seems to be the only solution for use cases like this. Hope this is an option for you too! If not, you can write a comment to boost the freq label at the issue a bit ;-)

EDIT(3):

I found a solution that seems to work, but you have to edit the ngsw-worker.js after the build process. Simply replace ngsw:db: with a name that is unique for the app (eg: ngsw:db:sw-app-one: for sw-app-one, ngsw:db:sw-app-two: for sw-app-two)

EDIT(4):

Sadly the solution does not work, the entries for the control key (eg: ngsw:db:sw-app-one:control) will be overwritten with the content of another app ... I will comment at the issue for further details ...

like image 138
skydever Avatar answered Oct 04 '22 16:10

skydever


I think you're onto something with your 3rd edit @skydever.

However if you look at the deleteAllCahces method of ngsw-worker.js you'll find that it will delete everything that starts with the ngsw: prefix. So instead of adding the unique app id after ngsw: rather replace ngsw: with ngsw-appone: (where appone is the unique app id for your app).

So your suggestion of editing the ngsw-worker.js after the build seems to work, and you have to replace ngsw: with ngsw-your_unique_app_id:

like image 21
Peter Salomonsen Avatar answered Oct 04 '22 16:10

Peter Salomonsen