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!!!
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.
RouterModule (enableTracing) You can set enableTracing to RouterModule which will log you all the route change events.
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.
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.
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
You likely need to configure your server to rewrite unmatched URLs to your index.html.
If you are using IIS,
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:
using live-server: https://www.npmjs.com/package/live-server
$live-server --entry-file=index.html
using nginx: http://nginx.org/en/docs/beginners_guide.html
error_page 404 /index.html
Tomcat - configuration of web.xml.
<error-page>
<error-code>404</error-code>
<location>/index.html</location>
</error-page>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With