SvelteKit 最新中文文档教程(18)—— 浅层路由和 Packaging

前言

Svelte,一个语法简洁、入门容易,面向未来的前端框架。

从 Svelte 诞生之初,就备受开发者的喜爱,根据统计,从 2019 年到 2024 年,连续 6 年一直是开发者最感兴趣的前端框架 No.1

image.png

Svelte 以其独特的编译时优化机制著称,具有轻量级高性能易上手等特性,非常适合构建轻量级 Web 项目

为了帮助大家学习 Svelte,我同时搭建了 Svelte 最新的中文文档站点。

如果需要进阶学习,也可以入手我的小册《Svelte 开发指南》,语法篇、实战篇、原理篇三大篇章带你系统掌握 Svelte!

欢迎围观我的“网页版朋友圈”、加入“冴羽·成长陪伴社群”,踏上“前端大佬成长之路”。

浅层路由

当您在 SvelteKit 应用中导航时,您会创建历史记录条目。点击后退和前进按钮会遍历这个条目列表,重新运行所有 load 函数,并在必要时替换页面组件。

有时,在不导航的情况下创建历史条目是有用的。例如,您可能想要显示一个模态对话框,用户可以通过返回导航来关闭它。这在移动设备上特别有价值,因为滑动手势通常比直接与 UI 交互更自然。在这些情况下,没有关联历史记录条目的模态可能会令人沮丧,因为用户可能会尝试向后滑动来关闭它,却发现自己到了错误的页面。

SvelteKit 通过 pushStatereplaceState 函数使这成为可能,这些函数允许您在不进行导航的情况下将状态与历史记录条目关联。例如,要实现一个由历史驱动的模态:

<!--- file: +page.svelte --->
<script>import { pushState } from '$app/navigation';import { page } from '$app/state';import Modal from './Modal.svelte';function showModal() {pushState('', {showModal: true});}
</script>{#if page.state.showModal}<Modal close={() => history.back()} />
{/if}

模态框可以通过返回导航(取消设置 page.state.showModal)或通过交互触发 close 回调运行来关闭。

API

pushState 的第一个参数是相对于当前 URL 的 URL。要保持在当前 URL,使用 ''

第二个参数是新的页面状态,可以通过 page 对象 作为 page.state 访问。您可以通过声明 App.PageState 接口(通常在 src/app.d.ts 中)来使页面状态类型安全。

要设置页面状态而不创建新的历史记录条目,请使用 replaceState 而不是 pushState

[!旧版说明] > $app/state 中的 page.state 是在 SvelteKit 2.12 中添加的。如果您使用的是较早版本或正在使用 Svelte 4,请使用 $app/stores 中的 $page.state

为路由加载数据

在进行浅层路由时,您可能想在当前页面内渲染另一个 +page.svelte。例如,点击照片缩略图可以弹出详细视图,而不需要导航到照片页面。

为此,您需要加载 +page.svelte 所需的数据。一个便捷的方法是在 <a> 元素的 click 处理程序中使用 preloadData。如果元素(或其父元素)使用 data-sveltekit-preload-data,数据将已经被请求,preloadData 将复用该请求。

<!--- file: src/routes/photos/+page.svelte --->
<script>import { preloadData, pushState, goto } from '$app/navigation';import { page } from '$app/state';import Modal from './Modal.svelte';import PhotoPage from './[id]/+page.svelte';let { data } = $props();
</script>{#each data.thumbnails as thumbnail}<ahref="/photos/{thumbnail.id}"onclick={async (e) => {if (innerWidth < 640        // 如果屏幕太小则退出|| e.shiftKey             // 或链接在新窗口中打开|| e.metaKey || e.ctrlKey // 或新标签页中打开 (mac: metaKey, win/linux: ctrlKey)// 也应考虑鼠标滚轮点击) return;// 阻止导航e.preventDefault();const { href } = e.currentTarget;// 运行 `load` 函数(或者说,获取由于 `data-sveltekit-preload-data`// 而已经在运行的 `load` 函数的结果)const result = await preloadData(href);if (result.type === 'loaded' && result.status === 200) {pushState(href, { selected: result.data });} else {// 出现问题!尝试导航goto(href);}}}><img alt={thumbnail.alt} src={thumbnail.src} /></a>
{/each}{#if page.state.selected}<Modal onclose={() => history.back()}><!-- 将页面数据传递给 +page.svelte 组件,就像 SvelteKit 在导航时那样 --><PhotoPage data={page.state.selected} /></Modal>
{/if}

注意事项

在服务端渲染期间,page.state 始终是一个空对象。对于用户首次访问的页面也是如此 — 如果用户重新加载页面(或从另一个文档返回),状态将不会应用,直到他们进行导航。

浅层路由是一个需要 JavaScript 才能工作的功能。在使用它时要谨慎,并尝试考虑在 JavaScript 不可用时的合理后备行为。

Packaging

您可以使用 SvelteKit 来构建应用程序和组件库,使用 @sveltejs/package 包(npx sv create 提供了设置此功能的选项)。

在创建应用程序时,src/routes 的内容是对外公开的部分;src/lib 包含应用程序的内部库。

组件库的结构与 SvelteKit 应用程序完全相同,区别在于 src/lib 是对外公开的部分,而根目录下的 package.json 用于发布包。src/routes 可能是随库附带的文档或演示站点,也可能只是开发时使用的沙箱。

运行 @sveltejs/package 提供的 svelte-package 命令会将 src/lib 的内容生成到一个 dist 目录中(可以配置),其中包括以下内容:

  • src/lib 中的所有文件。Svelte 组件会被预处理,TypeScript 文件会被转译为 JavaScript。
  • 为 Svelte、JavaScript 和 TypeScript 文件生成类型定义(d.ts 文件)。您需要安装 typescript >= 4.0.0 来支持此功能。类型定义文件会被放置在实现文件旁边,手动编写的 d.ts 文件将原样复制。您可以禁用生成,但我们强烈建议不要这样做 —— 使用您库的用户可能会需要这些文件来支持 TypeScript。

[!注意] @sveltejs/package 的第 1 版会生成一个 package.json。现在不再如此,它会使用项目中的 package.json 并验证其正确性。如果您仍然使用第 1 版,请查看此 PR 获取迁移说明。

package.json 的结构

因为您现在正在为公共使用构建一个库,因此 package.json 的内容变得更为重要。通过它,您可以配置包的入口点、发布到 npm 的文件以及库的依赖。我们将逐一介绍最重要的字段。

name

这是您包的名称,其他人可以使用该名称安装您的包,并可在 https://npmjs.com/package/<name> 网站上看到它。

{"name": "your-library"
}

在此处阅读关于它的更多内容。

license

每个包都应有一个 license 字段,以告知人们如何使用它。目前非常流行的一种许可证是 MIT,它在分发和复用方面非常宽松且无需担保。

{"license": "MIT"
}

在此处阅读关于它的更多内容。请注意,应在包中包含一个 LICENSE 文件。

files

该字段告诉 npm 哪些文件将被打包并上传到 npm。它应包含输出文件夹(默认为 dist)。您的 package.jsonREADMELICENSE 文件会始终被包括在内,因此您不需要指定它们。

{"files": ["dist"]
}

要排除不必要的文件(如单元测试,或者仅从 src/routes 导入的模块等)可以将它们添加到 .npmignore 文件中。这将导致包更小,安装速度更快。

在此处阅读关于它的更多内容。

exports

"exports" 字段包含包的入口点。如果您通过 npx sv create 设置了一个新的库项目,它会设置为单一出口,即包的根目录:

{"exports": {".": {"types": "./dist/index.d.ts","svelte": "./dist/index.js"}}
}

这告诉打包工具和工具链,您的包只有一个入口点,即根目录,所有内容应通过以下方式导入:

// @errors: 2307
import { Something } from 'your-library';

typessvelte 键是导出条件,它们告诉工具在查找 your-library 导入时应引入哪个文件:

  • TypeScript 看到 types 条件,会查找类型定义文件。如果您不发布类型定义,请忽略此条件。
  • 支持 Svelte 的工具会看到 svelte 条件,知道这是一个 Svelte 组件库。如果您发布的库不导出任何 Svelte 组件,并且也可以在非 Svelte 项目中使用(如 Svelte store 库),您可以将此条件替换为 default

[!注意] 早期版本的 @sveltejs/package 还添加了一个 package.json 导出。这不再是模板的一部分,因为所有工具都可以处理没有明确导出的 package.json

您可以根据需要调整 exports 并提供更多入口点。例如,如果您想直接暴露 src/lib/Foo.svelte 组件而不是通过 src/lib/index.js 文件重新导出组件,您可以创建以下导出映射……

{"exports": {"./Foo.svelte": {"types": "./dist/Foo.svelte.d.ts","svelte": "./dist/Foo.svelte"}}
}

……然后您的库的使用者可以用如下方式导入该组件:

// @filename: ambient.d.ts
declare module 'your-library/Foo.svelte';// @filename: index.js
// ---cut---
import Foo from 'your-library/Foo.svelte';

[!注意] 请注意,如果您提供类型定义,采用此方式可能需要额外处理。在此处阅读关于此问题的更多详细信息。

通常,exports 映射的每个键都是用户从您的包中导入某些内容的路径。而值则是将被导入的文件的路径或包含这些文件路径的导出条件映射。

在此处阅读关于 exports 的更多内容。

svelte

这是一个遗留字段,用于让工具识别 Svelte 组件库。如果使用 svelte 导出条件,它已不再必要,但为了向尚未了解导出条件的过时工具提供兼容性,建议保留它。它应指向您的根入口点。

{"svelte": "./dist/index.js"
}
sideEffects

package.json 中的 sideEffects 字段用于让打包工具判断模块是否可能包含副作用。如果模块在被导入时对其他脚本可见的行为产生变化(例如修改全局变量或内置 JavaScript 对象的原型),则视为有副作用。由于副作用可能会影响应用程序的其他部分,这些文件/模块无论其导出是否在应用程序中使用,都会被包括在最终的打包文件中。

sideEffects 字段中指定的模块会帮助打包工具更积极地从最终的打包文件中剔除未使用的导出(即 tree-shaking),从而生成更小更高效的打包文件。不同的打包工具以不同的方式处理 sideEffects。尽管 Vite 不需要此配置,但建议为库声明所有 CSS 文件具有副作用,以保持与 webpack 兼容。新创建的项目中的默认配置如下:

/// file: package.json
{"sideEffects": ["**/*.css"]
}

如果您的库中的脚本存在副作用,请确保更新 sideEffects 字段。在新创建的项目中,所有脚本默认标记为无副作用。如果错误地将包含副作用的文件标记为没有副作用,可能会导致功能异常。

如果您的包中有副作用的文件,可以通过数组指定这些文件:

/// file: package.json
{"sideEffects": ["**/*.css", "./dist/sideEffectfulFile.js"]
}

这样只会将指定的文件视为有副作用的文件。

TypeScript

即使您自己不使用 TypeScript,也应为您的库提供类型定义,这样使用您库的人可以获得正确的智能提示。@sveltejs/package 让生成类型的过程对您来说基本上是透明的。默认情况下,在打包您的库时,会为 JavaScript、TypeScript 和 Svelte 文件自动生成类型定义。您只需要确保 exports 映射中的 types 条件指向正确的文件。当通过 npx sv create 初始化库项目时,会自动设置为根导出。

然而,如果您除了根导出还有其他内容,例如提供 your-library/foo 导入,您需要额外注意提供类型定义。不幸的是,默认情况下 TypeScript 不会 为这种导出解析 types 条件,比如 { "./foo": { "types": "./dist/foo.d.ts", ... }}。相反,它会从库的根目录(即 your-library/foo.d.ts 而不是 your-library/dist/foo.d.ts)查找 foo.d.ts 文件。为了解决这个问题,您有两种选择:

第一种选择是要求使用您库的人在其 tsconfig.json(或 jsconfig.json)中将 moduleResolution 选项设置为 bundler(从 TypeScript 5 开始可用,未来是最佳推荐选项)、node16nodenext。这会使 TypeScript 实际查看 exports 映射并正确解析这些类型。

第二种选择是滥用 TypeScript 的 typesVersions 特性连接类型。typesVersionspackage.json 中的一个字段,TypeScript 根据 TypeScript 版本检查不同类型定义,同时也包含路径映射功能。我们利用该路径映射功能来满足需求。对于上面提到的 foo 导出,相应的 typesVersions 定义如下:

{"exports": {"./foo": {"types": "./dist/foo.d.ts","svelte": "./dist/foo.js"}},"typesVersions": {">4.0": {"foo": ["./dist/foo.d.ts"]}}
}

>4.0 表示如果使用的 TypeScript 版本大于 4,则 TypeScript 会检查内部映射。内部映射告诉 TypeScript your-library/foo 的类型定义在 ./dist/foo.d.ts 中,这实际上是对 exports 条件的复制。您还可以使用 * 通配符一次性提供多个类型定义而无需重复。如果选择使用 typesVersions,您需要通过它声明所有类型导入,包括根导入(定义为 "index.d.ts": [..])。

您可以在此处 阅读有关该功能的更多信息。

最佳实践

除非您计划将包仅供其他 SvelteKit 项目使用,否则应避免在包中使用 SvelteKit 特定模块(如 $app/environment)。例如,与其使用 import { browser } from '$app/environment',不如使用 import { BROWSER } from 'esm-env'(参见 esm-env 文档)。您可能还希望将当前 URL 或导航操作作为 prop 传入,而不是直接依赖 $app/state$app/navigation 等。这种更通用的编写方式还会使测试、UI 演示等工具的设置变得更加容易。

svelte.config.js(而非 vite.config.jstsconfig.json)中通过 aliases 添加别名,以便它们被 svelte-package 处理。

应仔细考虑对包的更改是错误修复、新功能还是重大更改,并相应地更新包版本。注意,如果从现有库中移除任何 exports 路径或其内的任何 export 条件,应将其视为重大更改。

{"exports": {".": {"types": "./dist/index.d.ts",
// 将 `svelte` 更改为 `default` 是重大更改:
---			"svelte": "./dist/index.js"---
+++			"default": "./dist/index.js"+++},
// 移除此项是重大更改:
---		"./foo": {"types": "./dist/foo.d.ts","svelte": "./dist/foo.js","default": "./dist/foo.js"},---
// 添加此项是可以的:
+++		"./bar": {"types": "./dist/bar.d.ts","svelte": "./dist/bar.js","default": "./dist/bar.js"}+++}
}

选项

svelte-package 接受以下选项:

  • -w/--watch — 监听 src/lib 的文件更改并重新构建包
  • -i/--input — 包含包所有文件的输入目录。默认为 src/lib
  • -o/--output — 处理后的文件写入的输出目录。您的 package.jsonexports 应指向该文件夹内的文件,files 数组也应包含该文件夹。默认为 dist
  • -t/--types — 是否创建类型定义(d.ts 文件)。我们强烈建议这样做,因为它有助于提升生态系统库的质量。默认为 true
  • --tsconfig — tsconfig 或 jsconfig 的路径。如果未提供,则会在工作区路径中搜索最近的 tsconfig/jsconfig。

发布

要发布生成的包:

npm publish

限制

所有的相对文件导入需要完全指定路径,遵守 Node 的 ESM 算法。这意味着对于像 src/lib/something/index.js 这样的文件,必须包括文件名和扩展名:

// @errors: 2307
import { something } from './something+++/index.js+++';

如果您使用 TypeScript,您需要以同样的方式导入 .ts 文件,但使用 .js 文件后缀而不是 .ts 文件后缀。(这是一个 TypeScript 的设计决策,超出我们的控制范围。)在您的 tsconfig.jsonjsconfig.json 中设置 "moduleResolution": "NodeNext" 将有助于解决这个问题。

除 Svelte 文件(预处理)和 TypeScript 文件(转换为 JavaScript)外,所有文件都按原样复制。

Svelte 中文文档

点击查看中文文档:

  1. SvelteKit 浅层路由
  2. SvelteKit Packaging

系统学习 Svelte,欢迎入手小册《Svelte 开发指南》。语法篇、实战篇、原理篇三大篇章带你系统掌握 Svelte!

此外我还写过 JavaScript 系列、TypeScript 系列、React 系列、Next.js 系列、冴羽答读者问等 14 个系列文章, 全系列文章目录:https://github.com/mqyqingfeng/Blog

欢迎围观我的“网页版朋友圈”、加入“冴羽·成长陪伴社群”,踏上“前端大佬成长之路”。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/900891.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Winform入门进阶企业级开发示例:http接口数据清洗转换、断线续传、mqtt数据传输实例详解(附代码资源下载)

场景 C#/Winform入门、进阶、强化、扩展、知识体系完善等知识点学习、性能优化、源码分析专栏分享: C#/Winform入门、进阶、强化、扩展、知识体系完善等知识点学习、性能优化、源码分析专栏分享_winform 强化学习-CSDN博客 如何将以上相关理论知识学以致用。下面针对Winform…

Python代码缩进统一规范

一、Python缩进的重要性:逻辑与可读性的桥梁 1. 语法规则的核心 Python与其他编程语言显著不同之处在于,它使用缩进来表示代码块的层次结构。不像C、Java等语言依靠大括号{}来明确函数体、循环体和条件语句的范围,Python完全依赖缩进来界定这些逻辑单元。例如,在一个if条…

asp.net core 项目发布到 IIS 服务器

目录 一、VS2022 发布 二、设置IIS服务 三、配置IIS管理器 &#xff08;一&#xff09;打开IIS管理器 &#xff08;二&#xff09;添加站台 &#xff08;三&#xff09;配置应用程式集区 四、安装ASP.NET Core Hosting Bundle 五、设定IIS的日志位置 六、测试 一、VS2…

spring mvc中不同服务调用类型(声明式(Feign)、基于模板(RestTemplate)、基于 SDK、消息队列、gRPC)对比详解

RestControllerAdvice 和 ControllerAdvice 对比详解 1. 基本概念 注解等效组合核心作用ControllerAdviceComponent RequestMapping&#xff08;隐式&#xff09;定义全局控制器增强类&#xff0c;处理跨控制器的异常、数据绑定或全局响应逻辑。RestControllerAdviceControll…

CVE-2025-29927 Next.js 中间件鉴权绕过漏洞

Next.js Next.js 是一个基于 React 的现代 Web 开发框架&#xff0c;用来构建高性能、可扩展的 Web 应用和网站。 CVE-2025-29927 Next.js 中间件鉴权绕过漏洞 CVE-2025-29927是Next.js框架中的一个授权绕过漏洞&#xff0c;允许攻击者通过特制的HTTP请求绕过在中间件中执行…

WP最主题专业的wordpress主题开发

WP最主题&#xff08;wpzui.com&#xff09; WP最主题是一个提供高品质WordPress主题的平台。它注重主题的设计和功能&#xff0c;旨在为用户提供美观且实用的主题选择。其主题通常具有良好的用户体验、丰富的自定义选项以及优化的性能&#xff0c;能够满足不同类型的网站搭建…

玩转代理 IP :实战爬虫案例

在现代互联网环境下&#xff0c;爬虫不仅是数据获取的利器&#xff0c;也成为应对网站反爬机制的技术博弈。而在这场博弈中&#xff0c;"代理 IP" 是核心武器之一。本文将以高匿名的代理ip为核心&#xff0c;结合 Python 实战、代理策略设计、高匿技巧与反封锁优化&a…

Vue 3 中 ref 与 reactive 的对比

Vue 3 中 ref 与 reactive 的对比 Vue 3 中 ref 与 reactive 的对比一、定义和基本使用refreactive 二、响应式原理refreactive 三、适用场景refreactive 四、注意事项refreactive Vue 3 中 ref 与 reactive 的对比 在 Vue 3 中&#xff0c;ref 和 reactive 都是用于创建响应式…

《Vue.js组件化开发实战:从安全纵深到性能跃迁》

开篇&#xff1a;组件化开发的工业革命 当全球500强企业的核心业务系统在12.12大促中经受每秒38万次请求冲击时&#xff0c;我们突然意识到&#xff1a;现代前端组件已不再是简单的UI积木&#xff0c;而是承载业务逻辑、安全防护、性能优化的纳米级作战单元。本文将从军工级系统…

从0到1的Python接口自动化学习路线

Python 是一门非常适合初学者且功能强大的编程语言,它在接口自动化测试领域具有广泛应用。 以下是一份针对 Python 与接口自动化测试的详细学习路线,帮助你从零开始学习并逐步掌握相关知识。 第一阶段:Python基础 目标:掌握 Python 基本语法和编程能力。 一、学习内容 1.…

HDCP(五)

HDCP 2.2 测试用例设计详解 基于HDCP 2.2 CTS v1.1规范及协议核心机制&#xff0c;以下从正常流程与异常场景两大方向拆解测试用例设计要点&#xff0c;覆盖认证、密钥管理、拓扑验证等关键环节&#xff1a; 1. 正常流程测试 1.1 单设备认证 • 测试目标&#xff1a;验证源设…

国标GB28181协议EasyCVR视频融合平台:5G时代远程监控赋能通信基站安全管理

一、背景介绍 随着移动通信行业的迅速发展&#xff0c;无人值守的通信基站建设规模不断扩大。这些基站大多建于偏远地区&#xff0c;周边人迹罕至、交通不便&#xff0c;给日常的维护带来了极大挑战。其中&#xff0c;位于空旷地带的基站设备&#xff0c;如空调、蓄电池等&…

A2L文件解析

目录 1 摘要2 A2L文件介绍2.1 A2L文件作用2.2 A2L文件格式详解2.2.1 A2L文件基本结构2.2.2 关键元素与声明2.2.3 完整A2L文件示例 3 总结 1 摘要 A2L文件&#xff08;也称为ASAP2文件&#xff09;是ECU开发的核心接口文件&#xff0c;用于标定、测量和诊断的关键配置文件&…

光学工程考研调剂推荐

一、调剂院校推荐 1. 华南农业大学 • 调剂分数参考&#xff1a;光学工程调剂生分数通常在300分左右&#xff0c;过国家线即可尝试。例如&#xff0c;2023年有297分考生成功调剂至此。 • 优势&#xff1a;对分数要求相对宽松&#xff0c;适合分数接近国家线的考生。 2. 安…

SQLite 注入:深入理解与防范策略

SQLite 注入:深入理解与防范策略 引言 SQLite,作为一款轻量级的数据库,被广泛应用于嵌入式系统、移动应用以及个人电脑中。尽管SQLite以其简单易用而受到青睐,但其安全机制若不恰当配置,则可能面临注入攻击的风险。本文旨在深入探讨SQLite注入的原理、类型及防范策略。 …

汽车与航空航天领域软件维护:深度剖析与未来展望

一、引言 在当今科技飞速发展的时代&#xff0c;汽车和航空航天领域的软件应用愈发广泛和深入&#xff0c;软件已成为这些行业系统的核心组成部分。从汽车的智能驾驶辅助系统到航空航天飞行器的飞行控制软件&#xff0c;软件的可靠性、安全性直接关系到整个系统的正常运行和人…

Jupyter notebook使用技巧

一、打开指定文件夹 在快捷方式目标中&#xff0c;使用如下代码 anaconda3\python.exe anaconda3\cwp.py anaconda3 anaconda3\python.exe anaconda3\Scripts\jupyter-notebook-script.py --notebook-dirD:\code\python

车辆视频检测器linux版对于密码中包含敏感字符的处理方法

由于密码中含有敏感字符&#xff0c;导致前端页面异常&#xff0c;图标变灰&#xff0c;坐标拾取打不开图像等&#xff0c;主要原因是&#xff1a;密码比较前后不一致&#xff0c;左边是Abc_110&#xff0c;右边是&#xff1a;Abc_110%2B&#xff0c;对于此问题&#xff0c;特别…

移动端六大语言速记:第12部分 - 测试与优化

移动端六大语言速记:第12部分 - 测试与优化 本文将对比Java、Kotlin、Flutter(Dart)、Python、ArkTS和Swift这六种移动端开发语言在测试与优化方面的特性,帮助开发者理解和掌握各语言的测试框架和性能优化技巧。 12. 测试与优化 12.1 单元测试框架对比 各语言单元测试框架…

Java—HTML:3D形变

今天我要介绍的是在Java HTML中CSS的相关知识点内容之一&#xff1a;3D形变&#xff08;3D变换&#xff09;。该内容包含透视&#xff08;属性&#xff1a;perspective&#xff09;&#xff0c;3D变换&#xff0c;3D变换函数以及案例演示&#xff0c; 接下来我将逐一介绍&…