Angular 18 Router生成styles.css等资源错误URL问题排查
问题描述
Angular 18 路由为 styles.css、main.js、polyfills.js 生成错误URL
正常可访问路径:
http://localhost:4200/users
相关组件
/users/users.component.ts
import {Component, OnInit, ViewChild, Input} from '@angular/core'; import { MatTableDataSource } from '@angular/material/table'; import {MatSort, Sort} from '@angular/material/sort'; import { User } from '../models/user.model'; import { UserService } from '../services/user.service'; import {ActivatedRoute, Router} from '@angular/router'; @Component({ selector: 'app-users', templateUrl: './users.component.html', styleUrls: ['./users.component.css'] }) export class UsersComponent implements OnInit { displayedColumns: string[] = ['id', 'name']; dataSource: MatTableDataSource<User>; users: User[] = []; constructor(private userService: UserService, private route: ActivatedRoute, private router: Router) { this.dataSource = new MatTableDataSource<User>(); } @ViewChild(MatSort) sort!: MatSort; @Input() filter!: User; ngOnInit() { this.userService.getUsers().subscribe((data: User[]) => { this.users = data; this.dataSource.data = this.users; this.dataSource.sort = this.sort; }); this.dataSource.filterPredicate = (data, filter: string): boolean => { return data.name.toLowerCase().includes(filter) || data.id.toString() === filter; }; } getInputValue(event: Event): string { const target = event.target as HTMLInputElement; return target ? target.value : ''; } applyFilter(filterValue: string) { filterValue = filterValue.trim().toLowerCase(); this.dataSource.filter = filterValue; // 更新URL,带上新的筛选值 this.router.navigate([], { relativeTo: this.route, queryParams: { find: filterValue }, queryParamsHandling: 'merge' }); } navigateToUserDetail(userId: number): void { this.router.navigate(['/users', userId]); } }
路由配置
/app/app.routes.ts
import { Routes } from '@angular/router'; import { UsersComponent } from './users/users.component'; import {UserDetailsComponent} from "./user-details/user-details.component"; import { CarsComponent } from './cars/cars.component'; import { CarDetailComponent } from './car-detail/car-detail.component'; export const routes: Routes = [ { path: 'users', component: UsersComponent }, { path: 'users/:id', component: UserDetailsComponent }, { path: 'cars', component: CarsComponent }, { path: 'cars/:id', component: CarDetailComponent }, { path: '', redirectTo: '/users', pathMatch: 'full' }, { path: '**', redirectTo: '/users' } ];
问题出现在以下路径:http://localhost:4200/users/1

用户详情组件
user-details.component.ts
import { Component, OnInit } from '@angular/core'; import { UserService } from '../services/user.service'; import { User } from '../models/user.model'; import { ActivatedRoute } from '@angular/router'; @Component({ selector: 'app-user-detail', templateUrl: './user-details.component.html', styleUrls: ['./user-details.component.css'] }) export class UserDetailsComponent implements OnInit { user!: User; displayedColumns: string[] = ['id', 'make', 'model', 'numberplate']; constructor(private userService: UserService, private route: ActivatedRoute) { } ngOnInit() { const userId = Number(this.route.snapshot.paramMap.get('id')); this.userService.getUserById(userId).subscribe(user => { this.user = user; }); } }
main.ts代码
import {CdkTableModule} from '@angular/cdk/table'; import {NgModule} from '@angular/core'; import {FormsModule, ReactiveFormsModule} from '@angular/forms'; import {bootstrapApplication, BrowserModule} from '@angular/platform-browser'; import {BrowserAnimationsModule} from '@angular/platform-browser/animations'; import {MatAutocompleteModule} from "@angular/material/autocomplete"; import {MatButtonModule} from "@angular/material/button"; import {MatButtonToggleModule} from "@angular/material/button-toggle"; import {MatCardModule} from "@angular/material/card"; import {MatCheckboxModule} from "@angular/material/checkbox"; import {MatChipsModule} from "@angular/material/chips"; import {MatStepperModule} from "@angular/material/stepper"; import {MatDatepickerModule} from "@angular/material/datepicker"; import {MatDialogModule} from "@angular/material/dialog"; import {MatDividerModule} from "@angular/material/divider"; import {MatExpansionModule} from "@angular/material/expansion"; import {MatGridListModule} from "@angular/material/grid-list"; import {MatIconModule} from "@angular/material/icon"; import {MatInputModule} from "@angular/material/input"; import {MatListModule} from "@angular/material/list"; import {MatMenuModule} from "@angular/material/menu"; import {MatNativeDateModule, MatRippleModule} from "@angular/material/core"; import {MatPaginatorModule} from "@angular/material/paginator"; import {MatProgressBarModule} from "@angular/material/progress-bar"; import {MatProgressSpinnerModule} from "@angular/material/progress-spinner"; import {MatRadioModule} from "@angular/material/radio"; import {MatSelectModule} from "@angular/material/select"; import {MatSidenavModule} from "@angular/material/sidenav"; import {MatSliderModule} from "@angular/material/slider"; import {MatSlideToggleModule} from "@angular/material/slide-toggle"; import {MatSnackBarModule} from "@angular/material/snack-bar"; import {MatTabsModule} from "@angular/material/tabs"; import {MatToolbarModule} from "@angular/material/toolbar"; import {MatTooltipModule} from "@angular/material/tooltip"; import {MatTableModule} from '@angular/material/table'; import {provideHttpClient} from "@angular/common/http"; import {RouterModule} from '@angular/router'; import {AppComponent} from "./app/app.component"; import {appConfig} from "./app/app.config"; import {UsersComponent} from "./app/users/users.component"; import {CarsComponent} from "./app/cars/cars.component"; import {CarDetailComponent} from "./app/car-detail/car-detail.component"; import { routes } from './app/app.routes'; import {MatSortModule} from "@angular/material/sort"; import {UserDetailsComponent} from "./app/user-details/user-details.component"; @NgModule({ exports: [ CdkTableModule, MatAutocompleteModule, MatButtonModule, MatButtonToggleModule, MatCardModule, MatCheckboxModule, MatChipsModule, MatStepperModule, MatDatepickerModule, MatDialogModule, MatDividerModule, MatExpansionModule, MatGridListModule, MatIconModule, MatInputModule, MatListModule, MatMenuModule, MatNativeDateModule, MatPaginatorModule, MatProgressBarModule, MatProgressSpinnerModule, MatRadioModule, MatRippleModule, MatSelectModule, MatSidenavModule, MatSliderModule, MatSlideToggleModule, MatSnackBarModule, MatTableModule, MatTabsModule, MatToolbarModule, MatTooltipModule, MatDialogModule, MatGridListModule, MatSortModule ] }) export class DemoMaterialModule {} @NgModule({ imports: [ BrowserModule, BrowserAnimationsModule, FormsModule, DemoMaterialModule, MatNativeDateModule, ReactiveFormsModule, RouterModule.forRoot(routes) ], declarations: [UsersComponent, UserDetailsComponent, CarsComponent, CarDetailComponent], bootstrap: [], providers: [provideHttpClient()] }) export class AppModule {} bootstrapApplication(AppComponent, appConfig) .catch((err) => console.error(err));
更新记录
更新1:初始index.html
<app-root></app-root>
更新2:问题解决
修改后的index.html:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>App</title> <base href="/"> </head> <body> <app-root></app-root> </body> </html>
在index.html的<head>标签中添加<base href="/">后,资源URL错误问题已解决。
内容的提问来源于stack exchange,提问作者J.Olufsen
相关产品推荐
相关产品推荐

