Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular RouterModule not woking in production

I have troubles getting my app working in production environment.

My app uses angular-jwt from @auth0/angular-jwt

If an user has an valid token, he will be forwarded to the MainScreenComponent, elsewhere he will be redirected to the login page.

import { AuthGuard } from './services/Authentication/auth-guard.service';
import { AuthGuardLogin } from './services/Authentication/auth-guard-login.service';
import { AuthService } from './services/Authentication/auth.service';
import { BrowserModule , HAMMER_GESTURE_CONFIG} from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { HttpClientModule } from '@angular/common/http';
import { NgModule } from '@angular/core';

import { RouterModule } from '@angular/router';
import { LoginComponent } from './components/login/login.component';
import { NotFoundComponent } from './components/not-found/not-found.component';
import { NoAccessComponent } from './components/no-access/no-access.component';
import { AppComponent } from './app.component';
import { environment } from '../environments/environment';
import { ServiceWorkerModule } from '@angular/service-worker';
import { MainScreenComponent } from './components/main-screen/main-screen.component';
import { JwtModule } from '@auth0/angular-jwt';

export function tokenGetter() {
  return localStorage.getItem('token');
}

@NgModule({
  declarations: [
    AppComponent,
    LoginComponent,
    NotFoundComponent,
    NoAccessComponent,
    MainScreenComponent
  ],
  imports: [
    BrowserModule,
    BrowserAnimationsModule,
    HttpClientModule,
    FormsModule,
    ReactiveFormsModule,
    ServiceWorkerModule.register('ngsw-worker.js', { enabled: environment.production }),
    RouterModule.forRoot([
       { path: '', component: MainScreenComponent , canActivate: [AuthGuard]},
       { path: 'login', component: LoginComponent,  canActivate: [AuthGuardLogin] },
       { path: '**', component: NotFoundComponent }
     ]),
     JwtModule.forRoot({
      config: {
        tokenGetter: tokenGetter,
        whitelistedDomains: environment.whiteListDomains,
      }
    })
  ],
  providers: [
  AuthService,
  AuthGuard,
  AuthGuardLogin,
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }

if I use ng serve everything works like expected, but after ng build --prod, I get an 404 if my initial URL is https://my-site:4300/login. In this case the RouterModule settings will be ignored.

If I type in https://my-site:4300, I will be redirected to https://my-site:4300/login and the login page will be displayed.

Any ideas?

========================

Update 31.10.2018:

Here is the AuthGuardLogin:

import { AuthService } from './auth.service';
import { Injectable } from '@angular/core';
import { CanActivate, Router } from '@angular/router';

@Injectable({
  providedIn: 'root'
})
export class AuthGuardLogin implements CanActivate {

  constructor( private router: Router, private authService: AuthService) { }

  canActivate() {
    if (this.authService.isLoggedIn()  === false) {
      return true; }

    this.router.navigate(['/']);
    return false;
  }
}

What I have now done, is hosting the website inside an Kestrel Server. Now it works perfect. Why? I don't know :-)!

By the way the Kestrel Server is hosted inside an Windows Service. So I can deploy that with our software package and install it via regular setup.

Best regards and thank you very much!!!

like image 882
reiniX86 Avatar asked Oct 25 '18 18:10

reiniX86


People also ask

What is the difference between RouterModule forRoot () and RouterModule forChild ()?

The forRoot() method creates an NgModule that contains all the directives, the given routes, and the Router service itself. The forChild() method creates an NgModule that contains all the directives and the given routes, but does not include the Router service.

What is the use of enableTracing in RouterModule?

RouterModule (enableTracing) You can set enableTracing to RouterModule which will log you all the route change events.

What is LoadChildren in Angular routing?

Use LoadChildren: Using this property will optimize your application's performance by only loading the nested route subtree when a user navigates to a particular URL that matches the current route path. It helps in keeping the nested routes table separate. You must specify a routing module for loadChildren.

How does router work in Angular?

Angular router can interpret a browser URL as an instruction to navigate to a client-generated view. It can pass optional parameters along to the supporting view component that help it decide what specific content to present.


2 Answers

I had a similar problem with a production environment when refresh was bugging out and couldnt identify the page.

I fixed it by using: imports: [RouterModule.forRoot(routes, { useHash: true })],

I am suggesting this solution since you said that when you typed the default url it worked and redirected in login, but when you typed /login it didnt.

useHash is used because angular is a spa and needs to load the main index.html first. In localhost and with webpack it works fine, but when you serve your app through a server you need to go throught the index.html on refresh and when you directly hit a url when not using the angular router.

Your urls will become a little ugly though because a # is going to be added before each url. For example domain/login will become domain/#/login

Hope it helps you

like image 70
Giwrgos Lampadaridis Avatar answered Oct 27 '22 21:10

Giwrgos Lampadaridis


You likely need to configure your server to rewrite unmatched URLs to your index.html.

If you are using IIS,

  1. Select the website under Sites,
  2. under IIS section, double-click on Error Pages
  3. Select 404 Status Code from the list and open in edit mode
  4. Select the radio button "Execute a URL on this site" and under URL textbox write "/" (without double quote)

You need to configure your production web server to always respond with the index.html whenever it detects a 404 - that way, Angular will always load and its routing service will handle the navigation on the client side. Or else you will have to use Hash location strategy.

EDIT: Configuration for other servers:

  1. using live-server: https://www.npmjs.com/package/live-server

    $live-server --entry-file=index.html

  2. using nginx: http://nginx.org/en/docs/beginners_guide.html

    error_page 404 /index.html

  3. Tomcat - configuration of web.xml.

    <error-page> <error-code>404</error-code> <location>/index.html</location> </error-page>

like image 22
Bhavik Patel Avatar answered Oct 27 '22 20:10

Bhavik Patel