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;
补充修复点
原组件代码存在两处语法错误,需修正:
export datax = 10→export let datax = 10(TypeScript导出变量需明确let/const关键字)- 未定义
options变量,需补充图表基础配置(示例已添加)
内容的提问来源于stack exchange,提问作者Ziur Olpa
相关产品推荐
相关产品推荐

