为什么在 svelte-kit 的 load 函数中,在服务器上运行代码时无法解析有效路由

Why in svelte-kit's load function a valid route can't be resolved when code runs on the server

在我的 svelte-kit 应用程序中,我遇到了这个 NODE 错误 ERR_INVALID_URL but was able to fix it with a solution provided in this 。不幸的是,关于为什么 NODE 无法解析 url 的更深入的解释——当代码在客户端上运行时,这显然只是一个有效的路由——被忽略了。

在 svelte-kit 的 load 函数中,我隐式 fetch -ing 一个,从 nodejs 的角度来看,无效的 url (ERR_INVALID_URL)

所以我想了解的是,为什么 NODE 无法 resolve/parse 给定的 url?

先决条件:

// in $lib/utils/http.js
export function post(endpoint, data = {}) {
    return fetch(endpoint, {
        method: "POST",
        credentials: "include",
        body: JSON.stringify(data),
        headers: {
          "Content-Type": "application/json",
        },
      }).then((r) => r.json());
}

// in routes/auth/login.js -> this endpoint can't be be found by NODE
export async function post({ locals, request }) {
    // ...code here
    return {
        body: request.json()
    }
}

这里要区分代码是运行在客户端还是服务端:

// in routes/login.svelte
import { browser } from '$app/env';
import { post } from '$lib/utils/http.js';

export async function load() {
    const { data } = someDataObject;
    if (browser) { // NODE wouldn't be able to find the endpoint in question ('/auth/login'), whereas the client does 
        return await post(`/auth/login`, { data }).then((response) => {
            // ...do something with the response
        });
    }
    return {};
}

感谢任何对此有所启发的解释。

您应该重构 load 函数以使用 SvelteKit 提供的 fetch。这将允许您在服务器上使用相对请求,这通常需要一个来源。来自 the docs(强调我的):

fetch is equivalent to the native fetch web API, with a few additional features:

  • it can be used to make credentialed requests on the server, as it inherits the cookie and authorization headers for the page request
  • it can make relative requests on the server (ordinarily, fetch requires a URL with an origin when used in a server context)
  • requests for endpoints go direct to the handler function during server-side rendering, without the overhead of an HTTP call
  • during server-side rendering, the response will be captured and inlined into the rendered HTML
  • during hydration, the response will be read from the HTML, guaranteeing consistency and preventing an additional network request

因此,从传递给 load 的参数中获取 fetch...

export async function load({ fetch }) {
    const { data } = someDataObject;
    return await post(`/auth/login`, fetch, { data }).then((response) => {
        // ...do something with the response
    });
}

... 并在您的 post 函数中使用它

// in $lib/utils/http.js
export function post(endpoint, fetch, data = {}) { /* rest as before */ }

一个 future enhancement to SvelteKit 可能会成功,因此您不必将 fetch 传递给您的效用函数,但这是您现在必须做的。