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

SvelteKit生产构建后路由页面依赖加载异常问题咨询

问题描述

在某SvelteKit项目中,开发环境下所有功能均正常,但生产构建完成后,部分路由页面的依赖无法正常工作。具体表现为:使用svelte-chartjs库引入的chart.js在开发环境运行良好,但直接访问生产构建后的/page路由时失效;无报错信息,且该页面的GET请求量明显减少,而从主页通过<a/>链接跳转至该路由则一切正常。请问这是什么原因?是否缺少相关配置?是否该路由不支持直接访问?

相关组件代码
<script lang="ts">
  import { Doughnut } from 'svelte-chartjs';
  export let datax = 10;
  export let datay = 20;

  import {
    Chart as ChartJS,
    Title,
    Tooltip,
    Legend,
    ArcElement,
    CategoryScale,
  } from 'chart.js';

  let chart: Doughnut;
  let data = {
    labels: ['Pension', 'Monthly paid out salary', 'Tax Under', 'Tax Over'],
    datasets: [
      {
        label: 'Danish Kronws',
        data: [datax, datay],
        backgroundColor: [
          'rgba(255, 134,159,0.4)',
          'rgba(98,  182, 239,0.4)',
        ],
        borderWidth: 2,
        borderColor: [
          'rgba(255, 134, 159, 1)',
          'rgba(98,  182, 239, 1)',
        ],
      },
    ],
  };

  ChartJS.register(Title, Tooltip, Legend, ArcElement, CategoryScale);

  $: {
    if (chart) {
      chart.data.datasets[0].data = [datax, datay];
    }
  }

  // 补充:原代码未定义options变量,需添加基础配置示例
  let options = {
    responsive: true,
    maintainAspectRatio: false
  };
</script>

<div class="chart">
  <Doughnut bind:chart data={data} options={options} />
</div>

<style>
  .chart{
    border-radius: 10px;
    box-shadow:0 0 15px 4px rgba(0,0,0,0.06);
    padding: 10px;
    width: 600px;
  }
</style>
原因分析与解决方案

核心原因

SvelteKit默认启用服务端渲染(SSR),而chart.js及其封装库svelte-chartjs依赖浏览器DOM环境。当直接访问路由时,SvelteKit会先在服务端渲染页面,此时没有DOM环境,导致图表初始化失败;而从主页通过<a/>跳转属于客户端导航,页面仅在浏览器端渲染,DOM环境正常,所以图表能正常工作。

解决方案

方案1:将图表组件改为仅客户端渲染

通过SvelteKit提供的browser环境变量,确保图表相关代码仅在浏览器中执行:

修改组件的<script>部分:

<script lang="ts">
  import { browser } from '$app/environment';
  export let datax = 10;
  export let datay = 20;

  let Doughnut: typeof import('svelte-chartjs').Doughnut;
  let ChartJS: typeof import('chart.js').Chart;
  let Title, Tooltip, Legend, ArcElement, CategoryScale;
  let chart: Doughnut;
  let data = {
    labels: ['Pension', 'Monthly paid out salary', 'Tax Under', 'Tax Over'],
    datasets: [
      {
        label: 'Danish Kronws',
        data: [datax, datay],
        backgroundColor: [
          'rgba(255, 134,159,0.4)',
          'rgba(98,  182, 239,0.4)',
        ],
        borderWidth: 2,
        borderColor: [
          'rgba(255, 134, 159, 1)',
          'rgba(98,  182, 239, 1)',
        ],
      },
    ],
  };
  let options = {
    responsive: true,
    maintainAspectRatio: false
  };

  // 仅在浏览器环境下加载依赖并初始化
  if (browser) {
    (async () => {
      const svelteChart = await import('svelte-chartjs');
      Doughnut = svelteChart.Doughnut;
      
      const chartJs = await import('chart.js');
      ({ ChartJS, Title, Tooltip, Legend, ArcElement, CategoryScale } = chartJs);
      ChartJS.register(Title, Tooltip, Legend, ArcElement, CategoryScale);
    })();
  }

  $: {
    if (chart) {
      chart.data.datasets[0].data = [datax, datay];
    }
  }
</script>

修改模板部分,确保仅当Doughnut加载完成后才渲染:

<div class="chart">
  {#if Doughnut}
    <Doughnut bind:chart data={data} options={options} />
  {/if}
</div>

方案2:禁用该路由的SSR

在对应路由的+page.ts文件中设置ssr: false,强制该页面仅在客户端渲染:

// src/routes/page/+page.ts
export const ssr = false;

补充修复点

原组件代码存在两处语法错误,需修正:

  1. export datax = 10 → export let datax = 10(TypeScript导出变量需明确let/const关键字)
  2. 未定义options变量,需补充图表基础配置(示例已添加)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 05:55:30