Angular独立组件导入模块后登录页报nextSibling空属性错误
问题:Angular项目部署Cloudflare后登录页加载失败,控制台抛出TypeError
错误信息
main-NTC3P324.js:7 ERROR TypeError: Cannot read properties of null (reading 'nextSibling')
项目目录结构
src |___app | |___base | | |___http | | | |___auth-inteceptor.ts | | |___pages | | | |___private | | | | |___BaseComponent.ts | | | |___public | | | | |___login | | | | | |___login.component.html | | | | | |___login.component.scss | | | | | |___login.component.ts | | | | |___BaseComponent.ts | | |___services | | | |___user.service.ts | | | |___cache.service.ts | | |___base.module.ts | |___lib | | |___model.ts | |___app.component.html | |___app.component.scss | |___app.component.ts | |___app.config.server.ts | |___app.config.ts | |___app.routes.server.ts | |___app.routes.ts | |___environment.ts |____routes.json |___index.html |___main.server.ts |___main.ts |___server.ts |___styles.scss
相关代码文件
src/main.ts
import { bootstrapApplication } from '@angular/platform-browser'; import { appConfig } from './app/app.config'; import { AppComponent } from './app/app.component'; bootstrapApplication(AppComponent, appConfig) .catch((err) => console.error(err));
src/app/app.config.ts
import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core'; import { provideRouter } from '@angular/router'; import { routes } from './app.routes'; import { provideClientHydration, withEventReplay } from '@angular/platform-browser'; export const appConfig: ApplicationConfig = { providers: [provideZoneChangeDetection({ eventCoalescing: true }), provideRouter(routes), provideClientHydration(withEventReplay())] };
src/app/app.component.ts
import { Component } from '@angular/core'; import { RouterOutlet } from '@angular/router'; import { BaseModule } from './base/base.module'; @Component({ selector: 'app-root', imports: [RouterOutlet, BaseModule], templateUrl: './app.component.html', styleUrl: './app.component.scss' }) export class AppComponent {}
src/app/app.component.html
<router-outlet />
src/app/app.routes.ts
import { Routes } from '@angular/router'; import { LoginComponent } from './base/pages/public/login/login.component'; export const routes: Routes = [ { path: '', component: LoginComponent } ];
src/app/environment.ts
export const BASE_URL = 'https://projectile.us'; export const API_BASE_URL = 'https://api.project.us';
src/app/base/base.module.ts
import { NgModule } from '@angular/core'; import { provideHttpClient, withFetch, withInterceptors } from '@angular/common/http'; import { BrowserModule } from '@angular/platform-browser'; import { CommonModule } from '@angular/common'; import { FormsModule } from '@angular/forms'; import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; import { MatDialogModule } from '@angular/material/dialog'; import { MatButtonModule } from '@angular/material/button'; import { MatAutocompleteModule } from '@angular/material/autocomplete'; import { MatCardModule } from '@angular/material/card'; import { MatCheckboxModule } from '@angular/material/checkbox'; import { MatBadgeModule } from '@angular/material/badge'; import { MatDatepickerModule } from '@angular/material/datepicker'; import { MatExpansionModule } from '@angular/material/expansion'; import { MatFormFieldModule } from '@angular/material/form-field'; 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 { 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 { MatSnackBarModule } from '@angular/material/snack-bar'; import { MatSortModule } from '@angular/material/sort'; import { MatTableModule } from '@angular/material/table'; import { MatTimepickerModule } from '@angular/material/timepicker'; import { MatTooltipModule } from '@angular/material/tooltip'; import { MatDividerModule } from '@angular/material/divider'; import { authInterceptor } from './http/auth-interceptor'; import { LoginComponent } from './pages/public/login/login.component'; const BASE = [ LoginComponent ] @NgModule({ declarations: BASE, imports: [ BrowserModule, CommonModule, FormsModule, BrowserAnimationsModule, MatDialogModule, MatButtonModule, MatAutocompleteModule, MatCardModule, MatCheckboxModule, MatBadgeModule, MatDatepickerModule, MatExpansionModule, MatFormFieldModule, MatGridListModule, MatIconModule, MatInputModule, MatListModule, MatMenuModule, MatPaginatorModule, MatProgressBarModule, MatProgressSpinnerModule, MatRadioModule, MatSelectModule, MatSidenavModule, MatSnackBarModule, MatSortModule, MatTableModule, MatTimepickerModule, MatTooltipModule, MatDividerModule, ], providers: [ provideHttpClient(withFetch(), withInterceptors([authInterceptor])) ], exports: BASE }) export class BaseModule {}
src/app/base/services/user.service.ts
import { Injectable, inject } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { Observable } from 'rxjs'; import { API_BASE_URL } from '../../environment'; import { User } from '../../lib/model'; export interface LoginResponse { user: User; authToken: string; } @Injectable({ providedIn: 'root' }) export class UserService { private http = inject(HttpClient); get authToken(): string | null { return localStorage.getItem('authToken'); } set authToken(value: string) { localStorage.setItem('authToken', value); } user!: User; constructor() { } login(email: string, password: string, remember: boolean): Observable<LoginResponse> { return this.http.post<LoginResponse>(API_BASE_URL + 'authenticate', { email, password, remember }); } isLoggedIn(): Observable<LoginResponse | false> { return this.http.get<LoginResponse | false>(API_BASE_URL + 'authenticated'); } }
src/app/base/services/cache.service.ts
import { Injectable } from '@angular/core'; @Injectable({ providedIn: 'root' }) export class CacheService extends Map<string, any> {}
src/app/base/http/auth-interceptor.ts
import { inject } from "@angular/core"; import { HttpRequest, HttpHandlerFn, HttpEvent } from "@angular/common/http"; import { Observable } from 'rxjs'; import { UserService } from "../services/user.service"; export function authInterceptor(req: HttpRequest<unknown>, next: HttpHandlerFn): Observable<HttpEvent<unknown>> { let svc = inject(UserService); let request = req; if(svc.authToken) { request = req.clone({ setHeaders: { Authorization: `Bearer ${svc.authToken}` } }); } return next(request); }
src/app/base/pages/public/BaseComponent.ts
import { Component, OnInit } from '@angular/core'; import { Router } from '@angular/router'; import { UserService } from '../../services/user.service'; import { CacheService } from '../../services/cache.service'; @Component({ selector: 'app-public-base', template: '', styles: [], standalone: false }) export class BaseComponent implements OnInit { constructor( protected router: Router, protected userService: UserService, protected cache: CacheService ) {} ngOnInit() { this.userService.isLoggedIn().subscribe(res => { if(res) { this.router.navigate(['/dashboard']); } }); } }
src/app/base/pages/public/login/login.component.ts
import { Component } from '@angular/core'; import { LoginResponse, UserService } from '../../../services/user.service'; import { BaseComponent } from '../BaseComponent'; import { Router } from '@angular/router'; import { CacheService } from '../../../services/cache.service'; @Component({ selector: 'app-login', templateUrl: './login.component.html', styleUrl: './login.component.scss', standalone: false }) export class LoginComponent extends BaseComponent { email: string = ''; password: string = ''; remember: boolean = false; constructor( router: Router, userService: UserService, cache: CacheService ) { super(router, userService, cache); } login() { this.userService.login(this.email, this.password, this.remember).subscribe(res => { this.userService.authToken = res.authToken; this.userService.user = res.user; this.router.navigate([this.cache.has('landingPage') ? this.cache.get('landingPage') : '/dashboard']); }); } }
src/app/base/pages/public/login/login.component.html
<div class="flexbox"> <div class="inner"> <form (ngSubmit)="login()"> <mat-card appearance="outlined"> <mat-card-header> <mat-card-title>Login</mat-card-title> </mat-card-header> <mat-card-content> <mat-form-field appearance="fill"> <mat-label>Email</mat-label> <input matInput [(ngModel)]="email" required email> </mat-form-field> <mat-form-field apperaence="fill"> <mat-label>Password</mat-label> <input matInput type="password" [(ngModel)]="password" required> </mat-form-field> <section> <mat-checkbox [(ngModel)]="remember">Remember Me</mat-checkbox> </section> </mat-card-content> <mat-card-actions> <button mat-raised-button color="primary" type="submit">Login</button> </mat-card-actions> </mat-card> </form> </div> </div>
src/app/base/pages/public/login/login.component.scss
.flexbox { display: flex; align-items: center; justify-content: center; } .flexbox > .inner { width: 400px; }
疑问
出现该错误是否是因为我在独立组件AppComponent中导入BaseModule,并路由到该模块下的LoginComponent导致的?
内容的提问来源于stack exchange,提问作者adam
相关产品推荐
相关产品推荐

