Angular RouterModule在生产环境中无法工作

6

我在生产环境中无法使我的应用程序工作。

我的应用程序使用@auth0/angular-jwt中的angular-jwt

如果用户拥有有效的令牌,他将被转发到MainScreenComponent,否则他将被重定向到登录页面。

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 { }

如果我使用ng serve,一切都像预期的那样工作,但在ng build --prod之后,如果我的初始URL是https://my-site:4300/login,我会得到404错误。在这种情况下,RouterModule设置将被忽略。
如果我输入https://my-site:4300,我将被重定向到https://my-site:4300/login,并显示登录页面。
有任何想法吗?
========================
更新于2018年10月31日:
这是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;
  }
}

现在我所做的是将网站托管在Kestrel服务器中。现在它运行得非常完美。为什么?我不知道 :-)!

顺便说一下,Kestrel服务器托管在Windows服务中。因此,我可以将其与我们的软件包一起部署,并通过常规安装进行安装。

最好的问候和非常感谢!!!


yes. <base href="/"> - reiniX86
让我们来看一下在 Git 上的 Angular CLI 问题:https://github.com/angular/angular-cli/issues/8515,也许你正在使用 ServiceWorker 和 base-href 遇到类似的问题。 - Daniel C.
谢谢您的提示,但我使用基本的http-server。https://www.npmjs.com/package/http-server。所以没有什么需要配置的。我也尝试了IIS,结果相同。 - reiniX86
你尝试过正确设置你的服务器吗?https://angular.io/guide/deployment#routed-apps-must-fallback-to-indexhtml - yurzui
这是由于您的服务器加载路由的方式造成的问题。对于IIS,解决方法是在web.config中添加一个新规则来处理加载index.html文件,无论何种路由都能够访问。 - mrtpain
显示剩余6条评论
3个回答

8

我在生产环境中遇到了类似的问题,当刷新页面时出现错误,无法识别该页面。

我通过以下方式解决了这个问题:

imports: [RouterModule.forRoot(routes, { useHash: true })],

我建议使用这种解决方案,因为你说当你输入默认的url时,它可以重定向到登录页面,但是当你输入/login时却不能。

使用useHash是因为Angular是单页应用程序,需要先加载主index.html。在本地主机和使用webpack时,它可以正常工作,但是当您通过服务器提供应用程序时,需要在刷新时经过index.html,并且在不使用Angular路由器时直接访问url。

但是,您的url会变得有点丑陋,因为每个url前都会添加一个#。例如,domain/login将变为domain/#/login。

希望对你有所帮助。


谢谢您的提示。如果我现在第一次加载带有登录路由的URL,我也会收到错误。但是如果它被缓存了,现在它就可以工作了。 - reiniX86

4
您可能需要配置您的服务器将未匹配的URL重写为index.html。
如果您使用的是IIS,
1. 选择“站点”下的网站, 2. 在IIS部分下,双击“错误页面” 3. 从列表中选择404状态代码并打开编辑模式 4. 选择单选按钮“在此站点上执行URL”,在URL文本框下写入“/”(不带双引号)
您需要配置生产Web服务器,以便每当它检测到404时始终使用index.html进行响应-这样,Angular将始终加载,并且其路由服务将处理客户端上的导航。 否则,您将不得不使用哈希位置策略。
编辑: 其他服务器的配置:
1. 使用live-server:https://www.npmjs.com/package/live-server $live-server --entry-file=index.html
2. 使用nginx:http://nginx.org/en/docs/beginners_guide.html error_page 404 /index.html
3. Tomcat-配置web.xml。 404 /index.html

谢谢!好主意!但我不会在IIS下托管它,因为这会使通过常规安装程序在目标机器上部署变得更加困难。大多数Windows机器默认情况下都没有安装IIS。 - reiniX86
正确。但是,您可以在部署此应用程序的任何服务器上(如Apache、Unix)设置此配置。您在这里遇到的问题是由于单页应用程序框架(例如Angular)的性质所致。 - Bhavik Patel
我已经更新了我的答案,并提供了其他服务器配置选项。希望能对你有所帮助。 - Bhavik Patel
1
是的,这取决于您正在运行的服务器类型。我使用的是IIS,解决此问题的方法是向web.config文件添加一个新规则。 - mrtpain

0
尝试添加文件 src/web.config ,内容如下:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <system.webServer>
    <rewrite>
      <rules>
        <rule name="Angular Routes" stopProcessing="true">
          <match url=".*" />
          <conditions logicalGrouping="MatchAll">
            <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
            <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
          </conditions>
          <action type="Rewrite" url="./index.html" />
        </rule>
      </rules>
    </rewrite>
    <staticContent>
      <remove fileExtension=".woff" />
      <mimeMap fileExtension=".woff" mimeType="application/font-woff" />
      <remove fileExtension=".woff2" />
      <mimeMap fileExtension=".woff2" mimeType="font/x-woff" />
      <remove fileExtension=".otf" />
      <mimeMap fileExtension=".otf" mimeType="font/otf" />
    </staticContent>
  </system.webServer>
</configuration>

它按预期为我工作。 我还在app.module.ts中添加了{ provide: LocationStrategy, useClass: PathLocationStrategy },并在index.html中添加了<base href="/">,但不确定它是否相关。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接