2

Currently, I am having an Angular application with PWA and whenever I add a new route let' say (http://www.something.com/child/childurl) to my application and deploy, and when the users directly open this URL, it always goes to default one where I mentioned { path: '**', redirectTo: '/home', pathMatch: 'full' } which is (http://www.something.com/home) in app.routing.module.ts

So the issue is that whenever I deploy Angular PWA application with a new route and the user accesses URL directly it will redirect it to /home and then the user sees a notification to update the app and then if users access the new route it works. But I wanted to make sure the new URL should work straight away

NOTE: This happens only when PWA is enabled in Angular

app.routing.module.ts

import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';

const routes: Routes = [
  {
    path: 'home',
    loadChildren: () => import('./modules/home/home.module').then((m) => m.HomeModule),
  },
  {
    path: 'lazymodule',
    loadChildren: () => import('./modules/child/child.module').then((m) => m.ChildRoutingModule ),
  },
  { path: '**', redirectTo: '/home', pathMatch: 'full' },
];

@NgModule({
  imports: [
    RouterModule.forRoot(routes, {
      scrollOffset: [0, 0],
      initialNavigation: 'enabled',
      scrollPositionRestoration: 'top',
    }),
  ],
  exports: [RouterModule],
})
export class AppRoutingModule {}

Child Lazy Loaded Module

child.routing.module.ts

import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { ChildComponent } from 'src/app/components/child.component';

const routes: Routes = [
  {
    path: 'childurl',
    component: ChildComponent
  },
];

@NgModule({
  imports: [RouterModule.forChild(routes)],
  exports: [RouterModule],
})
export class ChildRoutingModule { }

ngsw-config.json

{
  "$schema": "./node_modules/@angular/service-worker/config/schema.json",
  "index": "/index.html",
  "assetGroups": [
    {
      "name": "app",
      "installMode": "prefetch",
      "resources": {
        "files": [
          "/favicon.ico",
          "/index.html",
          "/manifest.webmanifest",
          "/*.css",
          "/*.js"
        ]
      }
    },
    {
      "name": "assets",
      "installMode": "lazy",
      "updateMode": "prefetch",
      "resources": {
        "files": [
          "/assets/**",
          "/*.(eot|svg|cur|jpg|png|webp|gif|otf|ttf|woff|woff2|ani)"
        ]
      }
    }
  ]
}

app.component.ts

Here I am showing the way to user to update the application if there is any

  ngOnInit(): void {

    if (this.swUpdate.isEnabled) {
      this.swUpdate.available.subscribe((evt) => {
        this.snackBarService.displayNotification({
          message: 'New version of app is available!',
          action: 'Launch',
          force: true,
          callback: () => {
            this.windowRef.nativeWindow.location.reload(true);
          },
        } as SnackBarNotification);
      });

      this.swUpdate
        .checkForUpdate()
        .then(() => {})
        .catch((err) => {
          console.error('error when checking for update', err);
        });
    }
  }
Mahesh G
  • 1,226
  • 4
  • 30
  • 57

1 Answers1

1

I had the same issue with PWA and found for myself one solution. Just remove redirection { path: '**', redirectTo: '/home', pathMatch: 'full' } from you root app.routing.module.ts.

Than create a component 404 for example and use it for routes **. In this case, users will see 404 component on any unknown route, but url in browser won't change.

In 404 component i check for updates with:

import { SwUpdate } from '@angular/service-worker';
...
constructor(private swUpdate: SwUpdate) {}
...
this.swUpdate.available.subscribe(() => {
   // here you can reload your page
   window.location.reload();
});

Now your app will be reloaded and users will see new page instead of 404 component.

On my app i added some information for users while checking for updates. You can check it on methodist.io, try to write any custom route.