Frequently asked questions
其他资源
请参阅的 Svelte FAQ和的 vite-plugin-svelte FAQ,以获取从这些库中产生的问题的答案。
我能用 SvelteKit 做什么?
查看有关项目类型的文档以获取更多详细信息。文档
如何在我的应用程序中包含 package.json 的详细信息?
如果您想在您的应用程序中包含应用程序的版本号或其他来自 package.json 的信息,您可以如此加载 JSON:
import import pkgpkg from './package.json' with { type: 'json' };如何修复尝试包含包时遇到的错误?
大多数与包含库相关的问题都是由于打包不正确造成的。您可以通过将其输入到publint 网站来检查库的打包是否与 Node.js 兼容。
以下是一些在检查库是否正确打包时需要注意的事项:
exports具有比其他入口字段(如main和module)更高的优先级。添加一个exports字段可能不向后兼容,因为它会阻止深度导入。- ESM 文件应以
.mjs结尾,除非设置了"type": "module",在这种情况下,任何 CommonJS 文件都应以.cjs结尾。 main应当在exports未定义时进行定义。它应为一个 CommonJS 或 ESM 文件,并遵守前面的项目符号。如果定义了module字段,则应指向一个 ESM 文件。- Svelte 组件应作为未编译的
.svelte文件分发,包内任何 JS 代码应仅以 ESM 格式编写。自定义脚本和样式语言,如 TypeScript 和 SCSS,应分别预处理为纯 JS 和 CSS。我们建议使用svelte-package对 Svelte 库进行打包,这将为您完成此操作。
库在浏览器中使用 Vite 效果最佳,尤其是在它们分发 ESM 版本时,尤其是当它们是 Svelte 组件库的依赖项时。您可能希望建议库作者提供 ESM 版本。然而,由于默认情况下,vite-plugin-svelte 将会请求 Vite 预打包它们,使用 esbuild 将它们转换为 ESM,因此 CommonJS (CJS) 依赖项也应该可以正常工作。
如果您仍然遇到问题,我们建议您同时搜索Vite 问题跟踪器和所涉及库的问题跟踪器。有时,通过调整optimizeDeps或ssr配置值可以解决这些问题,尽管我们建议这仅作为修复所涉及库的短期解决方案。
如何使用视图转换 API?
虽然 SvelteKit 没有与 视图过渡 的特定集成,你可以在 onNavigate 中调用 document.startViewTransition 来在每次客户端导航时触发视图过渡。
import { function onNavigate(callback: (navigation: import("@sveltejs/kit").OnNavigate) => MaybePromise<void | (() => void)>): voidA lifecycle function that runs the supplied callback immediately before we navigate to a new URL except during full-page navigations.
If you return a Promise, SvelteKit will wait for it to resolve before completing the navigation. This allows you to — for example — use document.startViewTransition. Avoid promises that are slow to resolve, since navigation will appear stalled to the user.
If a function (or a Promise that resolves to a function) is returned from the callback, it will be called once the DOM has updated.
onNavigate must be called during a component initialization. It remains active as long as the component is mounted.
onNavigate } from '$app/navigation';
function onNavigate(callback: (navigation: import("@sveltejs/kit").OnNavigate) => MaybePromise<void | (() => void)>): voidA lifecycle function that runs the supplied callback immediately before we navigate to a new URL except during full-page navigations.
If you return a Promise, SvelteKit will wait for it to resolve before completing the navigation. This allows you to — for example — use document.startViewTransition. Avoid promises that are slow to resolve, since navigation will appear stalled to the user.
If a function (or a Promise that resolves to a function) is returned from the callback, it will be called once the DOM has updated.
onNavigate must be called during a component initialization. It remains active as long as the component is mounted.
onNavigate((navigation: OnNavigatenavigation) => {
if (!var document: Documentdocument.Document.startViewTransition(callbackOptions?: ViewTransitionUpdateCallback): ViewTransitionstartViewTransition) return;
return new var Promise: PromiseConstructor
new <void | (() => void)>(executor: (resolve: (value: void | (() => void) | PromiseLike<void | (() => void)>) => void, reject: (reason?: any) => void) => void) => Promise<void | (() => void)>
Creates a new Promise.
Promise((resolve: (value: void | (() => void) | PromiseLike<void | (() => void)>) => voidresolve) => {
var document: Documentdocument.Document.startViewTransition(callbackOptions?: ViewTransitionUpdateCallback): ViewTransitionstartViewTransition(async () => {
resolve: (value: void | (() => void) | PromiseLike<void | (() => void)>) => voidresolve();
await navigation: OnNavigatenavigation.Navigation.complete: Promise<void>A promise that resolves once the navigation is complete, and rejects if the navigation
fails or is aborted. In the case of a willUnload navigation, the promise will never resolve
complete;
});
});
});更多内容,请参阅 Svelte 博客上的“解锁视图转换”。
如何设置数据库?
将查询数据库的代码放入服务器路由中 - 不要在.svelte 文件中查询数据库。您可以创建一个db.js或类似的文件,立即建立连接并使客户端在整个应用程序中作为单例可用。您可以在hooks.server.js中执行任何一次性设置代码,并将您的数据库助手导入到需要它们的任何端点。
您可以使用 Svelte CLI自动设置数据库集成。
如何使用客户端库访问document或window>?
如果您需要访问 文档 或 窗口 变量,或者需要仅在客户端运行的代码,您可以将它包裹在 浏览器 检查中:
import { const browser: booleantrue if the app is running in the browser.
browser } from '$app/environment';
if (const browser: booleantrue if the app is running in the browser.
browser) {
// client-only code here
}您也可以在onMount中运行代码,如果您想在组件首次渲染到 DOM 后运行它:
import { function onMount<T>(fn: () => NotFunction<T> | Promise<NotFunction<T>> | (() => any)): voidonMount, like $effect, schedules a function to run as soon as the component has been mounted to the DOM.
Unlike $effect, the provided function only runs once.
It must be called during the component’s initialisation (but doesn’t need to live inside the component;
it can be called from an external module). If a function is returned synchronously from onMount,
it will be called when the component is unmounted.
onMount functions do not run during server-side rendering.
onMount } from 'svelte';
onMount<void>(fn: () => void | (() => any) | Promise<void>): voidonMount, like $effect, schedules a function to run as soon as the component has been mounted to the DOM.
Unlike $effect, the provided function only runs once.
It must be called during the component’s initialisation (but doesn’t need to live inside the component;
it can be called from an external module). If a function is returned synchronously from onMount,
it will be called when the component is unmounted.
onMount functions do not run during server-side rendering.
onMount(async () => {
const { const method: anymethod } = await import('some-browser-only-library');
const method: anymethod('hello world');
});如果希望使用的库是无副作用的,您还可以静态导入它,在服务器端构建过程中它将被摇树优化,其中 onMount 将自动替换为空操作:
import { function onMount<T>(fn: () => NotFunction<T> | Promise<NotFunction<T>> | (() => any)): voidonMount, like $effect, schedules a function to run as soon as the component has been mounted to the DOM.
Unlike $effect, the provided function only runs once.
It must be called during the component’s initialisation (but doesn’t need to live inside the component;
it can be called from an external module). If a function is returned synchronously from onMount,
it will be called when the component is unmounted.
onMount functions do not run during server-side rendering.
onMount } from 'svelte';
import { module "some-browser-only-library"method } from 'some-browser-only-library';
onMount<void>(fn: () => void | (() => any) | Promise<void>): voidonMount, like $effect, schedules a function to run as soon as the component has been mounted to the DOM.
Unlike $effect, the provided function only runs once.
It must be called during the component’s initialisation (but doesn’t need to live inside the component;
it can be called from an external module). If a function is returned synchronously from onMount,
it will be called when the component is unmounted.
onMount functions do not run during server-side rendering.
onMount(() => {
module "some-browser-only-library"method('hello world');
});最后,您还可以考虑使用一个 {#await} 块:
<script>
import { browser } from '$app/environment';
const ComponentConstructor = browser ?
import('some-browser-only-library').then((module) => module.Component) :
new Promise(() => {});
</script>
{#await ComponentConstructor}
<p>Loading...</p>
{:then component}
<svelte:component this={component} />
{:catch error}
<p>Something went wrong: {error.message}</p>
{/await}<script lang="ts">
import { browser } from '$app/environment';
const ComponentConstructor = browser ?
import('some-browser-only-library').then((module) => module.Component) :
new Promise(() => {});
</script>
{#await ComponentConstructor}
<p>Loading...</p>
{:then component}
<svelte:component this={component} />
{:catch error}
<p>Something went wrong: {error.message}</p>
{/await}如何使用不同的后端 API 服务器?
您可以使用event.fetch从外部 API 服务器请求数据,但请注意,您需要处理CORS,这可能会导致一些复杂情况,例如通常需要预先发送请求,从而导致更高的延迟。向不同的子域发送请求也可能由于额外的 DNS 查找、TLS 设置等而增加延迟。如果您想使用这种方法,可能会发现handleFetch很有帮助。
另一种方法是设置代理以绕过 CORS 问题。在生产环境中,您会将路径如/api重写到 API 服务器;对于本地开发,使用 Vite 的server.proxy选项。
如何在生产环境中设置重写取决于您的部署平台。如果重写不是选项,您可以另加一个API 路由:
/** @type {import('./$types').RequestHandler} */
export function function GET({ params, url }: {
params: any;
url: any;
}): Promise<Response>
GET({ params: anyparams, url: anyurl }) {
return function fetch(input: string | URL | globalThis.Request, init?: RequestInit): Promise<Response> (+1 overload)fetch(`https://my-api-server.com/${params: anyparams.path + url: anyurl.search}`);
}import type { type RequestHandler = (event: Kit.RequestEvent<Record<string, any>, string | null>) => MaybePromise<Response>
type RequestHandler = (event: Kit.RequestEvent<Record<string, any>, string | null>) => MaybePromise<Response>
RequestHandler } from './$types';
export const const GET: RequestHandlerGET: type RequestHandler = (event: Kit.RequestEvent<Record<string, any>, string | null>) => MaybePromise<Response>
type RequestHandler = (event: Kit.RequestEvent<Record<string, any>, string | null>) => MaybePromise<Response>
RequestHandler = ({ params: Record<string, any>The parameters of the current route - e.g. for a route like /blog/[slug], a { slug: string } object.
params, url: URLThe requested URL.
url }) => {
return function fetch(input: string | URL | globalThis.Request, init?: RequestInit): Promise<Response> (+1 overload)fetch(`https://my-api-server.com/${params: Record<string, any>The parameters of the current route - e.g. for a route like /blog/[slug], a { slug: string } object.
params.path + url: URLThe requested URL.
url.URL.search: stringsearch}`);
};(请注意,您可能还需要代理 POST / PATCH 等请求,并根据需要转发 request.headers。)
如何使用中间件?
适配器节点构建一个中间件,您可以使用它与自己的服务器一起用于生产模式。在开发中,您可以通过使用 Vite 插件将中间件添加到 Vite。例如:
import { module "@sveltejs/kit/vite"sveltekit } from '@sveltejs/kit/vite';
/** @type {import('vite').Plugin} */
const const myPlugin: Plugin$1<any>myPlugin = {
OutputPlugin.name: stringname: 'log-request-middleware',
Plugin$1<any>.configureServer?: ObjectHook<ServerHook> | undefinedConfigure the vite server. The hook receives the
{@link
ViteDevServer
}
instance. This can also be used to store a reference to the server
for use in other hooks.
The hooks will be called before internal middlewares are applied. A hook
can return a post hook that will be called after internal middlewares
are applied. Hook can be async functions and will be called in series.
configureServer(server: ViteDevServerserver) {
server: ViteDevServerserver.ViteDevServer.middlewares: Connect.ServerA connect app instance.
- Can be used to attach custom middlewares to the dev server.
- Can also be used as the handler function of a custom http server
or as a middleware in any connect-style Node.js frameworks
middlewares.Connect.Server.use(fn: Connect.NextHandleFunction): Connect.Server (+3 overloads)Utilize the given middleware handle to the given route,
defaulting to /. This “route” is the mount-point for the
middleware, when given a value other than / the middleware
is only effective when that segment is present in the request’s
pathname.
For example if we were to mount a function at /admin, it would
be invoked on /admin, and /admin/settings, however it would
not be invoked for /, or /posts.
use((req: Connect.IncomingMessagereq, res: ServerResponse<IncomingMessage>res, next: Connect.NextFunctionnext) => {
var console: ConsoleThe console module provides a simple debugging console that is similar to the
JavaScript console mechanism provided by web browsers.
The module exports two specific components:
- A
Console class with methods such as console.log(), console.error() and console.warn() that can be used to write to any Node.js stream.
- A global
console instance configured to write to process.stdout and
process.stderr. The global console can be used without importing the node:console module.
Warning: The global console object’s methods are neither consistently
synchronous like the browser APIs they resemble, nor are they consistently
asynchronous like all other Node.js streams. See the note on process I/O for
more information.
Example using the global console:
console.log('hello world');
// Prints: hello world, to stdout
console.log('hello %s', 'world');
// Prints: hello world, to stdout
console.error(new Error('Whoops, something bad happened'));
// Prints error message and stack trace to stderr:
// Error: Whoops, something bad happened
// at [eval]:5:15
// at Script.runInThisContext (node:vm:132:18)
// at Object.runInThisContext (node:vm:309:38)
// at node:internal/process/execution:77:19
// at [eval]-wrapper:6:22
// at evalScript (node:internal/process/execution:76:60)
// at node:internal/main/eval_string:23:3
const name = 'Will Robinson';
console.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to stderr
Example using the Console class:
const out = getStreamSomehow();
const err = getStreamSomehow();
const myConsole = new console.Console(out, err);
myConsole.log('hello world');
// Prints: hello world, to out
myConsole.log('hello %s', 'world');
// Prints: hello world, to out
myConsole.error(new Error('Whoops, something bad happened'));
// Prints: [Error: Whoops, something bad happened], to err
const name = 'Will Robinson';
myConsole.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to err
console.Console.log(message?: any, ...optionalParams: any[]): void (+1 overload)Prints to stdout with newline. Multiple arguments can be passed, with the
first used as the primary message and all additional used as substitution
values similar to printf(3)
(the arguments are all passed to util.format()).
const count = 5;
console.log('count: %d', count);
// Prints: count: 5, to stdout
console.log('count:', count);
// Prints: count: 5, to stdout
See util.format() for more information.
log(`Got request ${req: Connect.IncomingMessagereq.IncomingMessage.url?: string | undefinedOnly valid for request obtained from
{@link
Server
}
.
Request URL string. This contains only the URL that is present in the actual
HTTP request. Take the following request:
GET /status?name=ryan HTTP/1.1
Accept: text/plain
To parse the URL into its parts:
new URL(`http://${process.env.HOST ?? 'localhost'}${request.url}`);
When request.url is '/status?name=ryan' and process.env.HOST is undefined:
$ node
> new URL(`http://${process.env.HOST ?? 'localhost'}${request.url}`);
URL {
href: 'http://localhost/status?name=ryan',
origin: 'http://localhost',
protocol: 'http:',
username: '',
password: '',
host: 'localhost',
hostname: 'localhost',
port: '',
pathname: '/status',
search: '?name=ryan',
searchParams: URLSearchParams { 'name' => 'ryan' },
hash: ''
}
Ensure that you set process.env.HOST to the server’s host name, or consider replacing this part entirely. If using req.headers.host, ensure proper
validation is used, as clients may specify a custom Host header.
url}`);
next: (err?: any) => voidnext();
});
}
};
/** @type {import('vite').UserConfig} */
const const config: UserConfigconfig = {
UserConfig.plugins?: PluginOption[] | undefinedArray of vite plugins to use.
plugins: [const myPlugin: Plugin$1<any>myPlugin, module "@sveltejs/kit/vite"sveltekit()]
};
export default const config: UserConfigconfig;查看Vite 的configureServer文档以获取更多详细信息,包括如何控制排序。
如何使用 Yarn?
支持 Yarn 2 吗?
有点问题。即插即用功能,即“pnp”,已损坏(它与 Node 模块解析算法不符,并且不支持与原生 JavaScript 模块一起使用,而 SvelteKit——以及越来越多的包——正是这样使用的)。您可以在您的.yarnrc.yml文件中使用nodeLinker: 'node-modules'来禁用 pnp,但可能直接使用 npm 或pnpm更简单,它们同样快速高效,但无需处理兼容性问题。
如何使用 Yarn 3?
当前最新版本的 Yarn(版本 3)中的 ESM 支持被视为实验性的。
以下似乎可以工作,尽管您的结果可能会有所不同。首先创建一个新的应用程序:
yarn create svelte myapp
cd myapp并启用 Yarn Berry:
yarn set version berry
yarn installYarn Berry 的一个更有趣的特性是能够拥有单个全局缓存包,而不是在磁盘上为每个项目存储多个副本。然而,将enableGlobalCache设置为 true 会导致构建失败,因此建议将以下内容添加到.yarnrc.yml文件中:
nodeLinker: 节点链接
这会导致包被下载到本地的 node_modules 目录中,但避免了上述问题,并且是目前使用 Yarn 3 版本的最佳选择。
Edit this page on GitHub llms.txt