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

Next.js迁移后Chart.js注解缺失、canvas元素渲染异常问题

问题根因

两类canvas渲染异常和SSR、插件注册、客户端初始化时机直接相关:

  • Chart.js注解缺失:你仅对react-chartjs-2的Chart组件做了ssr:false动态导入,但未注册chartjs-plugin-annotation插件。CRA环境下该插件大概率在项目入口文件被全局注册,迁移Next.js后模块作用域隔离,未显式注册的插件不会被Chart.js加载,这一问题和是否关闭SSR无直接关系。
  • ArcGIS 3D canvas渲染异常:3D WebGL渲染强依赖浏览器端window、WebGLRenderingContext全局API,需要DOM节点挂载完成后才能初始化上下文。如果ArcGIS相关模块在服务端渲染阶段被引入执行,会因拿不到浏览器API导致上下文初始化失败,3D元素无法绘制。
修复步骤

1. 修复Chart.js注解不显示问题

首先安装annotation插件依赖(未安装时执行):
npm install chartjs-plugin-annotation

修改父组件的Chart注册逻辑,将Annotation插件加入注册列表,同时优化动态导入配置:

// parent component 修正后的导入和注册部分
import dynamic from 'next/dynamic';
import {
  Chart as ChartJS,
  LinearScale,
  CategoryScale,
  BarElement,
  PointElement,
  LineElement,
  Legend,
  Tooltip,
} from 'chart.js';
// 新增annotation插件导入
import Annotation from 'chartjs-plugin-annotation';
import moment from 'moment-timezone';
import React, { useRef } from 'react';
import { ArrowRight } from '../../icons/ArrowRight';
import Link from 'next/link';
import { chartOptions } from '../../lib/chartOptions';

const Chart = dynamic((): any => import('react-chartjs-2').then((m: any) => m.Chart), {
  ssr: false,
  // 增加加载占位,避免组件 hydration 不匹配
  loading: () => <div className="h-[100px] w-[99%] bg-gray-100 animate-pulse"></div>
});

// 注册插件时加入Annotation
ChartJS.register(
  LinearScale,
  CategoryScale,
  BarElement,
  PointElement,
  LineElement,
  Legend,
  Tooltip,
  Annotation // 新增该行
);

// 其余组件逻辑保持不变
export const MarkupCard = ({ item }: any) => {
  // 原有逻辑不变
}

注意:如果使用Next.js 13+ App Router模式,该组件顶部需要新增'use client'指令,标记为客户端组件。

2. 修复ArcGIS 3D canvas渲染异常

所有ArcGIS 3D相关模块禁止在组件顶层导入,必须在useEffect内动态引入,确保仅在客户端DOM挂载完成后执行初始化:

// ArcGIS地图组件修正示例
import React, { useEffect, useRef } from 'react';
import dynamic from 'next/dynamic';

const ArcGISMap = () => {
  const mapContainer = useRef<HTMLDivElement>(null);

  useEffect(() => {
    let viewInstance: any = null;
    // 所有ArcGIS模块全部在useEffect内动态导入
    const initMap = async () => {
      const [Map, SceneView] = await Promise.all([
        import('@arcgis/core/Map'),
        import('@arcgis/core/views/SceneView')
      ]);
      
      const map = new Map.default({
        basemap: 'topo-vector',
        ground: 'world-elevation'
      });

      viewInstance = new SceneView.default({
        container: mapContainer.current,
        map: map,
        // 原有相机、图层配置保持不变
      });
    }

    initMap();
    // 组件卸载时销毁实例,避免内存泄漏
    return () => viewInstance?.destroy();
  }, []);

  return <div ref={mapContainer} className="w-full h-[600px]"></div>
}

// 整个地图组件关闭SSR
export default dynamic(() => Promise.resolve(ArcGISMap), { ssr: false });
效果对比
  • CRA环境正常效果:
    CRA环境下注解正常显示
  • 修复前Next.js环境异常效果:
    Next.js修复前注解缺失

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 06:18:21