在SvelteKit中使用SignalR遇相对路径解析错误求助
SvelteKit中SignalR相对路径解析失败的解决方案
问题背景
在SvelteKit项目中使用SignalR时,执行以下初始化代码出现错误:
const hubConnection = new HubConnectionBuilder().withUrl("/api/notifications").build();
错误提示:Cannot resolve '/api/notifications'
查看SignalR源码可知,错误触发自HttpConnection.js的路径解析逻辑:
_resolveUrl(url) { // startsWith is not supported in IE if (url.lastIndexOf("https://", 0) === 0 || url.lastIndexOf("http://", 0) === 0) { return url; } if (!Utils_1.Platform.isBrowser) { throw new Error(`Cannot resolve '${url}'.`); } ... }
而Utils.js中isBrowser的判断依赖浏览器环境的window和document对象:
class Platform { // react-native has a window but no document so we should check both static get isBrowser() { return !Platform.isNode && typeof window === "object" && typeof window.document === "object"; } ... }
使用绝对路径时错误消失,说明问题出在isBrowser返回false,即代码执行环境并非浏览器。
核心原因
SvelteKit默认启用服务端渲染(SSR),你的SignalR初始化代码可能在服务端执行了。服务端环境中不存在window和document对象,导致SignalR判定当前不是浏览器环境,拒绝解析相对路径。
解决方法
1. 用browser变量限定客户端执行
从SvelteKit导入browser变量,仅在浏览器环境初始化连接:
import { browser } from '$app/environment'; import { HubConnectionBuilder } from '@microsoft/signalr'; let hubConnection; if (browser) { hubConnection = new HubConnectionBuilder() .withUrl("/api/notifications") .build(); // 连接启动、事件监听等逻辑也需放在此判断内 }
2. 借助onMount钩子执行客户端逻辑
onMount是Svelte的生命周期钩子,仅在客户端渲染时触发,适合放置SignalR初始化代码:
import { onMount } from 'svelte'; import { HubConnectionBuilder } from '@microsoft/signalr'; let hubConnection; onMount(async () => { hubConnection = new HubConnectionBuilder() .withUrl("/api/notifications") .build(); try { await hubConnection.start(); console.log("SignalR连接成功"); } catch (err) { console.error("SignalR连接失败:", err); } });
3. 环境变量统一管理API地址(可选)
若需兼容开发/生产环境,可通过环境变量配置基础API地址,避免硬编码绝对路径:
- 在项目根目录创建
.env文件:
VITE_API_BASE_URL=https://your-production-domain.com
- 代码中读取环境变量并拼接路径:
import { browser } from '$app/environment'; import { HubConnectionBuilder } from '@microsoft/signalr'; let hubConnection; if (browser) { const baseUrl = import.meta.env.VITE_API_BASE_URL || window.location.origin; hubConnection = new HubConnectionBuilder() .withUrl(`${baseUrl}/api/notifications`) .build(); }
内容的提问来源于stack exchange,提问作者jandos
相关产品推荐
相关产品推荐

