带参数的Angular路由无法在新标签页打开的问题排查
带参数路由新标签页打开模块加载失败问题
问题现象
开发的Angular应用路由在应用内跳转正常,但带参数的链接复制到新标签页打开时出现模块加载失败:
- 无参数路由
http://localhost:4200/updates在应用内和新标签页均可正常访问 - 带参数路由
http://localhost:4200/updates/repositories/Test/units仅能在应用内正常工作,新标签页打开时触发以下错误:
Uncaught SyntaxError: expected expression, got '<' scripts.91672879d55182c59502.js:1 Loading module from “http://localhost:4200/updates/repositories/sumDev/main-es2017.233f600c1169f07fe825.js” was blocked because of a disallowed MIME type (“text/html”). units Loading failed for the module with source “http://localhost:4200/updates/repositories/sumDev/main-es2017.233f600c1169f07fe825.js”.
依赖配置
"dependencies": { "@angular-devkit/build-angular": "^0.1102.14", "@angular/animations": "~11.2.14", "@angular/cdk": "^11.2.13", "@angular/common": "~11.2.14", "@angular/compiler": "~11.2.14", "@angular/core": "~11.2.14", "@angular/forms": "~11.2.14", "@angular/localize": "^11.2.14", "@angular/material": "^11.2.13", "@angular/platform-browser": "~11.2.14", "@angular/platform-browser-dynamic": "~11.2.14", "@angular/router": "~11.2.14", "@auth0/angular-jwt": "^5.0.2", "@delite/dlt-icons": "^1.1.5", "classlist.js": "^1.1.20150312", "hammerjs": "^2.0.8", "keycloak-angular": "^8.2.0", "keycloak-js": "^13.0.0", "net": "^1.0.2", "ng-http-loader": "^5.1.0", "rxjs": "~6.6.7", "sockjs-client": "^1.6.1", "stompjs": "^2.3.3", "tslib": "^2.0.0", "zone.js": "~0.11.3" }, "devDependencies": { "@angular/cli": "~11.2.14", "@angular/compiler-cli": "~11.2.14", "@angular/language-service": "~11.2.14", "@types/core-js": "^2.5.4", "@types/jasmine": "~3.6.0", "@types/jasminewd2": "~2.0.3", "@types/node": "^12.11.1", "codelyzer": "^6.0.0", "jasmine-core": "~3.6.0", "jasmine-spec-reporter": "~5.0.0", "karma": "^6.3.4", "karma-chrome-launcher": "~3.1.0", "karma-coverage-istanbul-reporter": "~3.0.2", "karma-jasmine": "~4.0.0", "karma-jasmine-html-reporter": "^1.5.0", "protractor": "~7.0.0", "ts-node": "~7.0.0", "tslint": "~6.1.0", "typescript": "^4.0.8" }
路由模块配置
const routes: Routes = [{ path: '', canActivate: [AuthGuard], children: [ { path: '', redirectTo: "installer", pathMatch: "full" },{ path: 'updates', component: UpdateRepositoryComponent, children: [ { path: 'repositories/:name/units', component: UnitsComponent, } ] }] }] @NgModule({ imports: [RouterModule.forRoot(routes, {relativeLinkResolution: 'legacy'})], exports: [RouterModule] }) export class AppRoutingModule {}
当前导航方式
this.router.navigate([this.router.url + `/repositories/${name}/units`]);
问题原因
Angular是单页应用(SPA),所有路由均为前端路由。新标签页打开带参数路由时,浏览器会向服务器发送该路径的请求;若服务器未配置SPA路由支持,会将此路径当成静态资源路径查找文件,找不到则返回index.html(或404页面)。此时浏览器尝试加载的JS文件实际是HTML内容,进而触发语法错误和MIME类型不匹配问题。
另外,当前导航方式存在隐患:直接拼接router.url可能导致路径重复,虽表面能正常跳转,但可能影响路由生成的资源加载路径。
解决步骤
1. 修正前端导航方式
不要直接拼接router.url,改用相对路由方式,需在组件中注入ActivatedRoute:
// 组件构造函数注入依赖 constructor(private router: Router, private route: ActivatedRoute) {} // 使用相对路径导航 this.router.navigate(['repositories', name, 'units'], { relativeTo: this.route });
2. 配置服务器支持SPA路由
开发环境(ng serve)
Angular CLI开发服务器默认支持SPA路由,修正导航方式后通常可解决问题。若仍有异常,可尝试启动时指定根路径:
ng serve --base-href /
生产环境部署时
根据服务器类型配置路由重写,确保所有路由请求返回index.html:
- Nginx:在配置文件的location块中添加
location / { try_files $uri $uri/ /index.html; } - Apache:项目根目录创建
.htaccess文件并添加RewriteEngine On RewriteBase / RewriteRule ^index\.html$ - [L] RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule . /index.html [L] - Node.js Express:使用
express-history-api-fallback中间件const express = require('express'); const fallback = require('express-history-api-fallback'); const app = express(); const root = __dirname + '/dist/your-project-name'; app.use(express.static(root)); app.use(fallback('index.html', { root: root })); app.listen(4200);
3. 检查index.html的base href
确保index.html中的<base>标签设置正确,根路径部署时应为:
<base href="/">
内容的提问来源于stack exchange,提问作者Alexander Mladzhov
相关产品推荐
相关产品推荐

