从 Sapper 迁移
SvelteKit 是 Sapper 的继任者,并共享其设计的许多元素。
如果您有一个现有的 Sapper 应用程序,计划迁移到 SvelteKit,则需要进行一些更改。在迁移过程中,您可能会发现查看一些示例很有帮助。
package.json
type: “module”
将 "type": "module" 添加到您的 package.json 中。如果您使用的是 Sapper 0.29.3 或更高版本,则可以将此步骤与其余步骤分开作为增量迁移的一部分执行。
dependencies
如果您正在使用其中一个,则删除 polka 或 express,以及任何中间件,例如 sirv 或 compression。
devDependencies
从您的 devDependencies 中删除 sapper,并将其替换为 @sveltejs/kit 以及您计划使用的任何适配器(请参阅下一节)。
scripts
任何引用 sapper 的脚本都应更新
sapper build应使用 Node 适配器变为vite buildsapper export应使用静态 适配器变为vite buildsapper dev应变为vite devnode __sapper__/build应变为node build
项目文件
您的应用程序的大部分内容(在 src/routes 中)可以保留在原处,但一些项目文件需要移动或更新。
配置
您的 webpack.config.js 或 rollup.config.js 应替换为 svelte.config.js,如此处所述。Svelte 预处理器选项应移动到 config.preprocess。
您需要添加一个适配器。sapper build 大致相当于adapter-node,而 sapper export 大致相当于adapter-static,尽管您可能更喜欢使用为您的部署平台设计的适配器。
如果您正在使用未由Vite自动处理的文件类型的插件,则需要找到 Vite 等效项并将其添加到Vite 配置中。
src/client.js
此文件在 SvelteKit 中没有等效项。任何自定义逻辑(超出 sapper.start(...))都应在您的 +layout.svelte 文件中,在 onMount 回调内表达。
src/server.js
使用 adapter-node 时,等效项是自定义服务器。否则,此文件没有直接的等效项,因为 SvelteKit 应用程序可以在无服务器环境中运行。
src/service-worker.js
大多数来自 @sapper/service-worker 的导入在$service-worker中都有等效项
files未更改routes已删除shell现在是buildtimestamp现在是version
src/template.html
src/template.html 文件应重命名为 src/app.html。
删除 %sapper.base%、%sapper.scripts% 和 %sapper.styles%。将 %sapper.head% 替换为 %sveltekit.head%,并将 %sapper.html% 替换为 %sveltekit.body%。<div id="sapper"> 不再需要。
src/node_modules
Sapper 应用程序中的一种常见模式是将您的内部库放在 src/node_modules 内的目录中。这在 Vite 中不起作用,因此我们改为使用src/lib。
页面和布局
重命名的文件
路由现在仅由文件夹名称组成以消除歧义,通向 +page.svelte 的文件夹名称对应于路由。请参阅路由文档以获取概述。以下是旧/新的比较
| 旧的 | 新的 |
|---|---|
| routes/about/index.svelte | routes/about/+page.svelte |
| routes/about.svelte | routes/about/+page.svelte |
您的自定义错误页面组件应从 _error.svelte 重命名为 +error.svelte。任何 _layout.svelte 文件也应重命名为 +layout.svelte。任何其他文件都将被忽略。
导入
来自 @sapper/app 的 goto、prefetch 和 prefetchRoutes 导入应分别替换为来自$app/navigation的 goto、preloadData 和 preloadCode 导入。
来自 @sapper/app 的 stores 导入应替换 - 请参阅下面的Stores部分。
您之前从 src/node_modules 中的目录导入的任何文件都需要替换为$lib导入。
预加载
与以前一样,页面和布局可以导出一个函数,该函数允许在渲染发生之前加载数据。
此函数已从 preload 重命名为load,它现在位于其 +page.svelte(或 +layout.svelte)旁边的 +page.js(或 +layout.js)中,并且其 API 已更改。它不再有两个参数 - page 和 session - 而只有一个 event 参数。
不再有 this 对象,因此没有 this.fetch、this.error 或 this.redirect。相反,您可以从输入方法中获取fetch,并且error和redirect现在都已抛出。
存储
在 Sapper 中,您将获得对提供的存储的引用,如下所示
import { module "@sapper/app"stores } from '@sapper/app';
const { const preloading: anypreloading, const page: anypage, const session: anysession } = module "@sapper/app"stores();page 存储仍然存在;preloading 已替换为包含 from 和 to 属性的 navigating 存储。page 现在具有 url 和 params 属性,但没有 path 或 query。
您在 SvelteKit 中以不同的方式访问它们。stores 现在是 getStores,但在大多数情况下,这是不必要的,因为您可以直接从$app/stores导入 navigating 和 page。
路由
不再支持正则表达式路由。相反,请使用高级路由匹配。
片段
以前,布局组件接收一个 segment 属性,指示子片段。此属性已被删除;您应该使用更灵活的 $page.url.pathname 值来推导出您感兴趣的片段。
网址
在 Sapper 中,所有相对 URL 都相对于基本 URL 解析 - 通常是 /,除非使用了 basepath 选项 - 而不是相对于当前页面。
这会导致问题,并且在 SvelteKit 中不再是这种情况。相反,相对 URL 相对于当前页面(或目标页面,对于 load 函数中的 fetch URL)解析。在大多数情况下,使用根相对(即以 / 开头)URL 更容易,因为它们的含义不依赖于上下文。
<a> 属性
sapper:prefetch现在是data-sveltekit-preload-datasapper:noscroll现在是data-sveltekit-noscroll
端点
在 Sapper 中,服务器路由接收 Node 的 http 模块公开的 req 和 res 对象(或 Polka 和 Express 等框架提供的增强版本)。
SvelteKit 的设计使其对应用程序运行的位置无关 - 它可以在 Node 服务器上运行,但也可以在无服务器平台或 Cloudflare Worker 上运行。因此,您不再直接与 req 和 res 交互。您的端点需要更新以匹配新的签名。
为了支持这种环境无关的行为,fetch 现在在全局上下文中可用,因此您无需导入 node-fetch、cross-fetch 或类似的服务器端 fetch 实现即可使用它。
集成
有关集成的详细信息,请参阅集成。
HTML 压缩器
Sapper 默认包含 html-minifier。SvelteKit 没有包含它,但您可以将其作为生产依赖项添加,然后通过钩子使用它。
import { module "html-minifier"minify } from 'html-minifier';
import { const building: booleanSvelteKit analyses your app during the build step by running it. During this process, building is true. This also applies during prerendering.
building } from '$app/environment';
const const minification_options: {
collapseBooleanAttributes: boolean;
collapseWhitespace: boolean;
conservativeCollapse: boolean;
decodeEntities: boolean;
html5: boolean;
ignoreCustomComments: RegExp[];
minifyCSS: boolean;
... 8 more ...;
sortClassName: boolean;
}
minification_options = {
collapseBooleanAttributes: booleancollapseBooleanAttributes: true,
collapseWhitespace: booleancollapseWhitespace: true,
conservativeCollapse: booleanconservativeCollapse: true,
decodeEntities: booleandecodeEntities: true,
html5: booleanhtml5: true,
ignoreCustomComments: RegExp[]ignoreCustomComments: [/^#/],
minifyCSS: booleanminifyCSS: true,
minifyJS: booleanminifyJS: false,
removeAttributeQuotes: booleanremoveAttributeQuotes: true,
removeComments: booleanremoveComments: false, // some hydration code needs comments, so leave them in
removeOptionalTags: booleanremoveOptionalTags: true,
removeRedundantAttributes: booleanremoveRedundantAttributes: true,
removeScriptTypeAttributes: booleanremoveScriptTypeAttributes: true,
removeStyleLinkTypeAttributes: booleanremoveStyleLinkTypeAttributes: true,
sortAttributes: booleansortAttributes: true,
sortClassName: booleansortClassName: true
};
/** @type {import('@sveltejs/kit').Handle} */
export async function function handle(input: {
event: RequestEvent;
resolve(event: RequestEvent, opts?: ResolveOptions): MaybePromise<Response>;
}): MaybePromise<...>
handle({ event: RequestEvent<Partial<Record<string, string>>, string | null>event, resolve: (event: RequestEvent, opts?: ResolveOptions) => MaybePromise<Response>resolve }) {
let let page: stringpage = '';
return resolve: (event: RequestEvent, opts?: ResolveOptions) => MaybePromise<Response>resolve(event: RequestEvent<Partial<Record<string, string>>, string | null>event, {
ResolveOptions.transformPageChunk?(input: {
html: string;
done: boolean;
}): MaybePromise<string | undefined>
Applies custom transforms to HTML. If done is true, it’s the final chunk. Chunks are not guaranteed to be well-formed HTML
(they could include an element’s opening tag but not its closing tag, for example)
but they will always be split at sensible boundaries such as %sveltekit.head% or layout/page components.
transformPageChunk: ({ html: stringhtml, done: booleandone }) => {
let page: stringpage += html: stringhtml;
if (done: booleandone) {
return const building: booleanSvelteKit analyses your app during the build step by running it. During this process, building is true. This also applies during prerendering.
building ? module "html-minifier"minify(let page: stringpage, const minification_options: {
collapseBooleanAttributes: boolean;
collapseWhitespace: boolean;
conservativeCollapse: boolean;
decodeEntities: boolean;
html5: boolean;
ignoreCustomComments: RegExp[];
minifyCSS: boolean;
... 8 more ...;
sortClassName: boolean;
}
minification_options) : let page: stringpage;
}
}
});
}请注意,当使用 vite preview 测试站点的生产版本时,prerendering 为 false,因此要验证压缩的结果,您需要直接检查构建的 HTML 文件。