SvelteKit响应式语句fetch接口报ERR_INVALID_URL错误原因及修复方法
错误产生原因
这个错误是服务端渲染(SSR)阶段执行fetch请求导致的:
- SvelteKit默认会先在服务端(Node.js环境)渲染首屏页面,你写的无依赖
$:响应式块会在组件初始化的SSR阶段就执行 - Node.js环境自带的原生
fetch实现不支持直接传入相对路径(比如/api/demo),它要求传入完整的带域名的合法URL,只有浏览器环境的原生fetch会自动基于当前页面的域名补全相对路径,因此服务端执行时会直接抛出ERR_INVALID_URL错误 - 额外问题:你写的无依赖
$:块没有绑定任何响应式变量,后续组件内任意响应式状态更新都会重复触发接口请求,会造成无意义的性能浪费。
修复方案
根据业务场景选以下任意一种方案即可:
方案1:仅在客户端发起请求(适合不需要首屏SSR携带数据的场景)
把接口调用逻辑移到onMount生命周期中,这个钩子只会在浏览器端hydration阶段执行,不会在SSR阶段运行,此时的fetch是浏览器原生实现,可以正常解析相对路径。
修改后的/index.svelte代码:
<script lang="ts"> import { onMount } from 'svelte'; // 仅组件挂载到浏览器后执行 onMount(() => { fetchEndpoint(); }); async function fetchEndpoint() { try { const res = await fetch('/api/demo'); // 后续自行处理响应逻辑即可 } catch(e) { console.log(`Failed load endpoint. ${e}`); } } </script>
方案2:使用SvelteKit提供的load函数请求(官方推荐的最佳实践)
SvelteKit的load函数会注入一个经过框架封装的fetch实例,这个实例在服务端运行时会自动补全URL域名,还能直接调用本地API接口无需发起真实HTTP请求,性能更好,同时支持SSR阶段就拿到数据填充首屏。
你当前用的是SvelteKit旧版路由格式,修改后的/index.svelte代码:
<script context="module" lang="ts"> export async function load({ fetch }) { try { const res = await fetch('/api/demo'); return { props: { demoData: await res.text() } } } catch(e) { console.log(`Failed load endpoint. ${e}`); return { props: { demoData: null } } } } </script> <script lang="ts"> // 接收load函数返回的数据 export let demoData: string | null; </script> <!-- 页面中直接使用demoData即可 -->
内容的提问来源于stack exchange,提问作者Codey
相关产品推荐
相关产品推荐

