You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 22:35:55