首页 > 解决方案 > 角度路由在生产构建中不起作用

问题描述

我正在开发一个 Angular 项目,它是一个带有登录页面的网络应用程序。该项目配置为在命中基本 URL 时显示登录,并在尝试访问会话中没有有效令牌的应用程序时重定向到登录页面。

该应用程序包含在其自己的模块中,该模块执行所有内部路由。

在这两种情况下一切正常:

ng serve
ng build
npx lite-server --baseDir="dist/frontend"

然后在使用生产标志构建时,路由中断。以下两种方式的行为相同:

ng build --prod
npx lite-server --baseDir="dist/frontend"
ng build --prod
firebase deploy

当我尝试访问“客户端”模块 ( http://host/client/anything ) 中的任何内容时,应用程序会再次将我重定向到着陆点 ( http://host/landing ),无论如何,如果粘贴 URL在浏览器栏中或通过登陆中的控件访问。

我已经阅读了用于部署的 Angular 文档,但在我的案例中已经配置了提到的提示。在那里阅读其他类似的堆栈帖子我找不到解决方案。

到目前为止我尝试了什么:

启用跟踪让我看到路由器确实在尝试访问登录页面,但是我没有得到的东西在中间中断。生产构建跟踪是:

main-es2015.4665a3d5fdcea262528d.js:1 路由器事件:Ee
main-es2015.4665a3d5fdcea262528d.js:1 NavigationStart(id: 5, url: '/client')
main-es2015.4665a3d5fdcea262528d.js:1 Ee {id:5,url:“/client”,navigationTrigger:“imperative”,restoredState:null}id:5navigationTrigger:“imperative”restoredState:nullurl:“/client”__proto__:我们
main-es2015.4665a3d5fdcea262528d.js:1 路由器事件:重新
main-es2015.4665a3d5fdcea262528d.js:1 RoutesRecognized(id: 5, url: '/client', urlAfterRedirects: '/client', state: Route(url:'', path:'') { Route(url:'client ', path:'client') { Route(url:'', path:'') } } )
main-es2015.4665a3d5fdcea262528d.js:1 Re {id: 5, url: "/client", urlAfterRedirects: "/client", state: At}
main-es2015.4665a3d5fdcea262528d.js:1 路由器事件:Oe
main-es2015.4665a3d5fdcea262528d.js:1 GuardsCheckStart(id: 5, url: '/client', urlAfterRedirects: '/client', state: Route(url:'', path:'') { Route(url:'client ', path:'client') { Route(url:'', path:'') } } )
main-es2015.4665a3d5fdcea262528d.js:1 Oe {id: 5, url: "/client", urlAfterRedirects: "/client", state: At}
main-es2015.4665a3d5fdcea262528d.js:1 路由器事件:xe
main-es2015.4665a3d5fdcea262528d.js:1 ChildActivationStart(路径:'')
main-es2015.4665a3d5fdcea262528d.js:1 xe {快照:Tt}
main-es2015.4665a3d5fdcea262528d.js:1 路由器事件:Fe
main-es2015.4665a3d5fdcea262528d.js:1 ActivationStart(路径:'client')
main-es2015.4665a3d5fdcea262528d.js:1 Fe {snapshot: Tt}

main-es2015.4665a3d5fdcea262528d.js:1 路由器事件:_e
main-es2015.4665a3d5fdcea262528d.js:1 NavigationCancel(id: 5, url: '/client')
main-es2015.4665a3d5fdcea262528d.js:1 _e {id: 5, url: "/client", reason: "导航 ID 5 不等于当前导航 ID 6"}

main-es2015.4665a3d5fdcea262528d.js:1 路由器事件:Ee
main-es2015.4665a3d5fdcea262528d.js:1 NavigationStart(id: 6, url: '/login?returnUrl=%2Fclient')
main-es2015.4665a3d5fdcea262528d.js:1 Ee {id: 6, url: "/login?returnUrl=%2Fclient", navigationTrigger: "imperative", restoreState: null}
main-es2015.4665a3d5fdcea262528d.js:1 路由器事件:重新
main-es2015.4665a3d5fdcea262528d.js:1 RoutesRecognized(id: 6, url: '/login?returnUrl=%2Fclient', urlAfterRedirects: '/login?returnUrl=%2Fclient', state: Route(url:'', path: '') { Route(url:'login', path:'login') } )
main-es2015.4665a3d5fdcea262528d.js:1 Re {id: 6, url: "/login?returnUrl=%2Fclient", urlAfterRedirects: "/login?returnUrl=%2Fclient", state: At}
main-es2015.4665a3d5fdcea262528d.js:1 路由器事件:Oe
main-es2015.4665a3d5fdcea262528d.js:1 GuardsCheckStart(id: 6, url: '/login?returnUrl=%2Fclient', urlAfterRedirects: '/login?returnUrl=%2Fclient', state: Route(url:'', path: '') { Route(url:'login', path:'login') } )
main-es2015.4665a3d5fdcea262528d.js:1 Oe {id: 6, url: "/login?returnUrl=%2Fclient", urlAfterRedirects: "/login?returnUrl=%2Fclient", 状态: At}
main-es2015.4665a3d5fdcea262528d.js:1 路由器事件:xe
main-es2015.4665a3d5fdcea262528d.js:1 ChildActivationStart(路径:'')
main-es2015.4665a3d5fdcea262528d.js:1 xe {快照:Tt}
main-es2015.4665a3d5fdcea262528d.js:1 路由器事件:Fe
main-es2015.4665a3d5fdcea262528d.js:1 ActivationStart(路径:'登录')
main-es2015.4665a3d5fdcea262528d.js:1 Fe {snapshot: Tt}
main-es2015.4665a3d5fdcea262528d.js:1 路由器事件:De
main-es2015.4665a3d5fdcea262528d.js:1 GuardsCheckEnd(id: 6, url: '/login?returnUrl=%2Fclient', urlAfterRedirects: '/login?returnUrl=%2Fclient', state: Route(url:'', path: '') { Route(url:'login', path:'login') } , shouldActivate: true)
main-es2015.4665a3d5fdcea262528d.js:1 De {id: 6, url: "/login?returnUrl=%2Fclient", urlAfterRedirects: "/login?returnUrl=%2Fclient", state: At, shouldActivate: true}
main-es2015.4665a3d5fdcea262528d.js:1 路由器事件:Pe
main-es2015.4665a3d5fdcea262528d.js:1 ResolveStart(id: 6, url: '/login?returnUrl=%2Fclient', urlAfterRedirects: '/login?returnUrl=%2Fclient', state: Route(url:'', path: '') { Route(url:'login', path:'login') } )
main-es2015.4665a3d5fdcea262528d.js:1 Pe {id: 6, url: "/login?returnUrl=%2Fclient", urlAfterRedirects: "/login?returnUrl=%2Fclient", 状态: At}
main-es2015.4665a3d5fdcea262528d.js:1 路由器事件:Te
main-es2015.4665a3d5fdcea262528d.js:1 ResolveEnd(id: 6, url: '/login?returnUrl=%2Fclient', urlAfterRedirects: '/login?returnUrl=%2Fclient', state: Route(url:'', path: '') { Route(url:'login', path:'login') } )
main-es2015.4665a3d5fdcea262528d.js:1 Te {id: 6, url: "/login?returnUrl=%2Fclient", urlAfterRedirects: "/login?returnUrl=%2Fclient", 状态: At}

main-es2015.4665a3d5fdcea262528d.js:1 路由器事件:_e
main-es2015.4665a3d5fdcea262528d.js:1 NavigationCancel(id: 6, url: '/login?returnUrl=%2Fclient')
main-es2015.4665a3d5fdcea262528d.js:1 _e {id: 6, url: "/login?returnUrl=%2Fclient", 原因: "导航 ID 6 不等于当前导航 ID 7"}

main-es2015.4665a3d5fdcea262528d.js:1 路由器事件:Ee
main-es2015.4665a3d5fdcea262528d.js:1 NavigationStart(id: 7, url: '/')
main-es2015.4665a3d5fdcea262528d.js:1 Ee {id: 7, url: "/", navigationTrigger: "imperative", restoreState: null}
main-es2015.4665a3d5fdcea262528d.js:1 路由器事件:我
main-es2015.4665a3d5fdcea262528d.js:1 ActivationEnd(路径:'登录')
main-es2015.4665a3d5fdcea262528d.js:1 我{快照:Tt}
main-es2015.4665a3d5fdcea262528d.js:1 路由器事件:Ne
main-es2015.4665a3d5fdcea262528d.js:1 ChildActivationEnd(路径:'')
main-es2015.4665a3d5fdcea262528d.js:1 Ne {快照:Tt}
main-es2015.4665a3d5fdcea262528d.js:1 路由器事件:重新
main-es2015.4665a3d5fdcea262528d.js:1 RoutesRecognized(id: 7, url: '/', urlAfterRedirects: '/landing', state: Route(url:'', path:'') { Route(url:'landing' , 路径:'着陆') } )
main-es2015.4665a3d5fdcea262528d.js:1 Re {id: 7, url: "/", urlAfterRedirects: "/landing", state: At}
main-es2015.4665a3d5fdcea262528d.js:1 路由器事件:Oe
main-es2015.4665a3d5fdcea262528d.js:1 GuardsCheckStart(id: 7, url: '/', urlAfterRedirects: '/landing', state: Route(url:'', path:'') { Route(url:'landing' , 路径:'着陆') } )
main-es2015.4665a3d5fdcea262528d.js:1 Oe {id: 7, url: "/", urlAfterRedirects: "/landing", state: At}
main-es2015.4665a3d5fdcea262528d.js:1 路由器事件:xe
main-es2015.4665a3d5fdcea262528d.js:1 ChildActivationStart(路径:'')
main-es2015.4665a3d5fdcea262528d.js:1 xe {快照:Tt}
main-es2015.4665a3d5fdcea262528d.js:1 路由器事件:Fe
main-es2015.4665a3d5fdcea262528d.js:1 ActivationStart(路径:'登陆')
main-es2015.4665a3d5fdcea262528d.js:1 Fe {snapshot: Tt}
main-es2015.4665a3d5fdcea262528d.js:1 路由器事件:De
main-es2015.4665a3d5fdcea262528d.js:1 GuardsCheckEnd(id: 7, url: '/', urlAfterRedirects: '/landing', state: Route(url:'', path:'') { Route(url:'landing' , path:'landing') } , shouldActivate: true)
main-es2015.4665a3d5fdcea262528d.js:1 De {id: 7, url: "/", urlAfterRedirects: "/landing", state: At, shouldActivate: true}
main-es2015.4665a3d5fdcea262528d.js:1 路由器事件:Pe
main-es2015.4665a3d5fdcea262528d.js:1 ResolveStart(id: 7, url: '/', urlAfterRedirects: '/landing', state: Route(url:'', path:'') { Route(url:'landing' , 路径:'着陆') } )
main-es2015.4665a3d5fdcea262528d.js:1 Pe {id: 7, url: "/", urlAfterRedirects: "/landing", state: At}
main-es2015.4665a3d5fdcea262528d.js:1 路由器事件:Te
main-es2015.4665a3d5fdcea262528d.js:1 ResolveEnd(id: 7, url: '/', urlAfterRedirects: '/landing', state: Route(url:'', path:'') { Route(url:'landing' , 路径:'着陆') } )
main-es2015.4665a3d5fdcea262528d.js:1 Te {id: 7, url: "/", urlAfterRedirects: "/landing", state: At}
main-es2015.4665a3d5fdcea262528d.js:1 路由器事件:我
main-es2015.4665a3d5fdcea262528d.js:1 ActivationEnd(路径:'登陆')
main-es2015.4665a3d5fdcea262528d.js:1 我{快照:Tt}
main-es2015.4665a3d5fdcea262528d.js:1 路由器事件:Ne
main-es2015.4665a3d5fdcea262528d.js:1 ChildActivationEnd(路径:'')
main-es2015.4665a3d5fdcea262528d.js:1 Ne {快照:Tt}
main-es2015.4665a3d5fdcea262528d.js:1 路由器事件:be
main-es2015.4665a3d5fdcea262528d.js:1 NavigationEnd(id: 7, url: '/', urlAfterRedirects: '/landing')
main-es2015.4665a3d5fdcea262528d.js:1 是 {id: 7, url: "/", urlAfterRedirects: "/landing"}
main-es2015.4665a3d5fdcea262528d.js:1 路由器事件:Le
main-es2015.4665a3d5fdcea262528d.js:1 滚动(锚点:'null',位置:'null')
main-es2015.4665a3d5fdcea262528d.js:1 Le {routerEvent: be, position: null, anchor: null}

导航被取消两次。第一个应该是因为 auth-guard 在尝试获取“客户端”模块时返回 false ,但根据记录的原因似乎是另一个原因。

开发构建跟踪完全不同:

platform-b​​rowser.js:96 路由器事件:NavigationStart
platform-b​​rowser.js:87 NavigationStart(id: 5, url: '/client')
platform-b​​rowser.js:87 NavigationStart {id: 5, url: "/client", navigationTrigger: "imperative", restoreState: null}
​ 路由器事件:RoutesRecognized
​ RoutesRecognized(id: 5, url: '/client', urlAfterRedirects: '/client', state: Route(url:'', path:'') { Route(url:'client', path:'client') { 路线(网址:'',路径:'')} })
​ RoutesRecognized {id: 5, url: "/client", urlAfterRedirects: "/client", state: RouterStateSnapshot}
​ 路由器事件:GuardsCheckStart
​ GuardsCheckStart(id: 5, url: '/client', urlAfterRedirects: '/client', state: Route(url:'', path:'') { Route(url:'client', path:'client') { 路线(网址:'',路径:'')} })
​ GuardsCheckStart {id: 5, url: "/client", urlAfterRedirects: "/client", state: RouterStateSnapshot}
​ 路由器事件:ChildActivationStart
​ ChildActivationStart(路径:'')
​ ChildActivationStart {快照:ActivatedRouteSnapshot}
​ 路由器事件:ActivationStart
​ ActivationStart(路径:'客户端')
​ ActivationStart {快照:ActivatedRouteSnapshot}
​ 路由器事件:NavigationCancel
​ NavigationCancel(id: 5, url: '/client')
​ NavigationCancel {id: 5, url: "/client", reason: "导航ID 5不等于当前导航id 6"}
​ 路由器事件:NavigationStart
​ NavigationStart(id: 6, url: '/login?returnUrl=%2Fclient')
​ NavigationStart {id: 6, url: "/login?returnUrl=%2Fclient", navigationTrigger: "imperative", restoreState: null}
​ 路由器事件:RoutesRecognized
​ RoutesRecognized(id: 6, url: '/login?returnUrl=%2Fclient', urlAfterRedirects: '/login?returnUrl=%2Fclient', state: Route(url:'', path:'') { Route(url: '登录',路径:'登录')})
​ RoutesRecognized {id: 6, url: "/login?returnUrl=%2Fclient", urlAfterRedirects: "/login?returnUrl=%2Fclient", state: RouterStateSnapshot}
​ 路由器事件:GuardsCheckStart
​ GuardsCheckStart(id: 6, url: '/login?returnUrl=%2Fclient', urlAfterRedirects: '/login?returnUrl=%2Fclient', state: Route(url:'', path:'') { Route(url: '登录',路径:'登录')})
​ GuardsCheckStart {id: 6, url: "/login?returnUrl=%2Fclient", urlAfterRedirects: "/login?returnUrl=%2Fclient", state: RouterStateSnapshot}
​ 路由器事件:ChildActivationStart
platform-b​​rowser.js:87 ChildActivationStart(路径:'')
platform-b​​rowser.js:87 ChildActivationStart {快照:ActivatedRouteSnapshot}
platform-b​​rowser.js:96 路由器事件:ActivationStart
platform-b​​rowser.js:87 ActivationStart(路径:'登录')
platform-b​​rowser.js:87 ActivationStart {快照:ActivatedRouteSnapshot}
platform-b​​rowser.js:96 路由器事件:GuardsCheckEnd
platform-b​​rowser.js:87 GuardsCheckEnd(id: 6, url: '/login?returnUrl=%2Fclient', urlAfterRedirects: '/login?returnUrl=%2Fclient', state: Route(url:'', path:'' ) { Route(url:'login', path:'login') } , shouldActivate: true)
platform-b​​rowser.js:87 GuardsCheckEnd {id: 6, url: "/login?returnUrl=%2Fclient", urlAfterRedirects: "/login?returnUrl=%2Fclient", state: RouterStateSnapshot, shouldActivate: true}
platform-b​​rowser.js:96 路由器事件:ResolveStart
platform-b​​rowser.js:87 ResolveStart(id: 6, url: '/login?returnUrl=%2Fclient', urlAfterRedirects: '/login?returnUrl=%2Fclient', state: Route(url:'', path:'' ) { 路由(url:'login', path:'login') })
platform-b​​rowser.js:87 ResolveStart {id: 6, url: "/login?returnUrl=%2Fclient", urlAfterRedirects: "/login?returnUrl=%2Fclient", state: RouterStateSnapshot}
platform-b​​rowser.js:96 路由器事件:ResolveEnd
platform-b​​rowser.js:87 ResolveEnd(id: 6, url: '/login?returnUrl=%2Fclient', urlAfterRedirects: '/login?returnUrl=%2Fclient', state: Route(url:'', path:'' ) { 路由(url:'login', path:'login') })
platform-b​​rowser.js:87 ResolveEnd {id: 6, url: "/login?returnUrl=%2Fclient", urlAfterRedirects: "/login?returnUrl=%2Fclient", state: RouterStateSnapshot}
platform-b​​rowser.js:96 路由器事件:ActivationEnd
platform-b​​rowser.js:87 ActivationEnd(路径:'登录')
platform-b​​rowser.js:87 ActivationEnd {快照:ActivatedRouteSnapshot}
platform-b​​rowser.js:96 路由器事件:ChildActivationEnd
platform-b​​rowser.js:87 ChildActivationEnd(路径:'')
platform-b​​rowser.js:87 ChildActivationEnd {快照:ActivatedRouteSnapshot}
platform-b​​rowser.js:96 路由器事件:NavigationEnd
platform-b​​rowser.js:87 NavigationEnd(id: 6, url: '/login?returnUrl=%2Fclient', urlAfterRedirects: '/login?returnUrl=%2Fclient')
platform-b​​rowser.js:87 NavigationEnd {id: 6, url: "/login?returnUrl=%2Fclient", urlAfterRedirects: "/login?returnUrl=%2Fclient"}
platform-b​​rowser.js:96 路由器事件:滚动

任何帮助表示赞赏。提前致谢。

标签: angularrouterproduction

解决方案


如果您使用 firebase 托管来托管您的构建,则需要启用对 index.html 的重写。

您可以通过添加以下部分在 firebase.json 文件中执行此操作rewrites

{
  "hosting": {
    "public": "dist/browser",
    "rewrites": [
      {
        "source": "**",
        "destination": "/index.html"
      }
    ],
    ...
  }
}



推荐阅读