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

Angular 18项目出现[vite] /home页面30秒未渲染内部服务器错误

Angular 18 + Vite 随机出现「Page /home did not render in 30 seconds」错误排查

错误日志

9:20:15 PM [vite] Internal server error: Page /home did not render in 30 seconds.
      at Timeout.<anonymous> (/Users/jan/Projekts/PflanzenApp/node_modules/@angular/build/src/utils/server-rendering/render-page.js:90:90)
      at Timeout.timer (/Users/jan/Projekts/PflanzenApp/node_modules/zone.js/fesm2015/zone-node.js:2198:37)
      at _ZoneDelegate.invokeTask (/Users/jan/Projekts/PflanzenApp/node_modules/zone.js/fesm2015/zone-node.js:398:33)
      at _ZoneImpl.runTask (/Users/jan/Projekts/PflanzenApp/node_modules/zone.js/fesm2015/zone-node.js:158:47)
      at invokeTask (/Users/jan/Projekts/PflanzenApp/node_modules/zone.js/fesm2015/zone-node.js:479:34)
      at Timeout.ZoneTask.invoke (/Users/jan/Projekts/PflanzenApp/node_modules/zone.js/fesm2015/zone-node.js:468:48)
      at Timeout.data.args.<computed> (/Users/jan/Projekts/PflanzenApp/node_modules/zone.js/fesm2015/zone-node.js:2180:32)
      at listOnTimeout (node:internal/timers:573:17)
      at process.processTimers (node:internal/timers:514:7)

问题根源分析

从你的HomePageComponent代码来看,错误的核心原因是SSR(服务器端渲染)环境下未正确处理定时器:

  1. ngOnInit中启动的setInterval会在服务器端持续运行,且不会随页面渲染完成自动清除,导致服务器进程资源被持续占用,当并发请求或资源不足时就会触发渲染超时。
  2. checkWatering方法每秒更新组件的days/hours等全局属性,触发频繁的Angular变更检测,进一步加重服务器渲染线程的负载。
  3. 额外bug:当前代码中多个固定植物的倒计时会互相覆盖(最后一个植物的倒计时会覆盖之前的),因为这些属性是组件级别的,而非每个植物独立持有。

修复方案

1. 区分环境启动定时器

仅在浏览器环境中启动定时器,避免SSR进程被无意义的定时器占用:

import { Component, OnInit, OnDestroy, Inject, PLATFORM_ID } from '@angular/core';
import { isPlatformBrowser } from '@angular/common';
// 其他导入保持不变

export class HomePageComponent implements OnInit, OnDestroy {
  plants: Plant[] = [];
  pinnedPlants: Plant[] = [];
  private intervalId: number | null = null; // 保存定时器ID用于销毁

  constructor(
    private plantService: PlantService,
    @Inject(PLATFORM_ID) private platformId: Object // 注入平台标识
  ) {
    this.plants = plantService.getOwnedPlants();
  }

  ngOnInit(): void {
    this.plants = this.plantService.getOwnedPlants();
    this.pinnedPlants = this.plants.filter(plant => plant.pinned);
    this.pinnedPlants.forEach(plant => this.updatePinnedPlant(plant));
    
    // 仅在浏览器环境启动定时器
    if (isPlatformBrowser(this.platformId)) {
      this.intervalId = window.setInterval(() => this.checkWatering(), 1000);
    }
  }

  // 组件销毁时清除定时器,避免内存泄漏
  ngOnDestroy(): void {
    if (this.intervalId) {
      clearInterval(this.intervalId);
    }
  }

  // 其他方法保持不变...
}

2. 优化倒计时数据结构

让每个植物独立持有倒计时属性,避免全局属性覆盖和不必要的变更检测:

  • 先修改Plant类,添加倒计时相关字段:
export class Plant {
  // 原有属性(如pinned、waterTime、maintenance等)
  days: number = 0;
  hours: number = 0;
  minutes: number = 0;
  seconds: number = 0;
  waterAmount: number = 0;
}
  • 然后修改checkWatering方法:
checkWatering(): void {
  const currentTime = new Date();
  this.pinnedPlants.forEach(plant => {
    let timeTillWater = plant.waterTime.getTime() - currentTime.getTime();
    // 更新当前植物的倒计时属性
    plant.days = Math.floor(timeTillWater / (24 * 60 * 60 * 1000));
    plant.hours = Math.floor((timeTillWater % (24 * 60 * 60 * 1000)) / (60 * 60 * 1000));
    plant.minutes = Math.floor((timeTillWater % (60 * 60 * 1000)) / (60 * 1000));
    plant.seconds = Math.floor((timeTillWater % (60 * 1000)) / 1000);

    let multiplier = 1;
    switch (plant.maintenance) {
      case 'Monthly':
        multiplier = 30;
        break;
      case 'Weekly':
        multiplier = 7;
        break;
      case 'Medium':
      case 'Daily':
      default:
        multiplier = 1;
    }

    plant.waterAmount = plant.water * multiplier;

    if (timeTillWater <= 0) {
      console.log("Gießen")   
    }     
  });
}

3. 可选:启用OnPush变更检测策略

进一步减少变更检测频率,提升性能:

@Component({
  selector: 'app-home-page',
  standalone: true,
  imports: [QuoteComponent, RouterLink, WeatherDisplayComponent, CommonModule, NgIf],
  templateUrl: './home-page.component.html',
  styleUrl: './home-page.component.css',
  changeDetection: ChangeDetectionStrategy.OnPush // 添加这一行
})

内容的提问来源于stack exchange,提问作者jamakr4

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 10:26:01