格式化过去 發表於 2025-4-2 20:09:00

SvelteKit 最新中文文档教程(17)—— 仅服务端模块和快照

<h2 id="前言">前言</h2>
<p>Svelte,一个语法简洁、入门容易,面向未来的前端框架。</p>
<p>从 Svelte 诞生之初,就备受开发者的喜爱,根据统计,<strong>从 2019 年到 2024 年,连续 6 年一直是开发者最感兴趣的前端框架 No.1</strong>:</p>
<p><img src="https://yayujs-blog.oss-cn-beijing.aliyuncs.com/405488775-48df16b1-939c-489b-8d52-6071869893f0.png"></p>
<p>Svelte 以其独特的编译时优化机制著称,具有<strong>轻量级</strong>、<strong>高性能</strong>、<strong>易上手</strong>等特性,<strong>非常适合构建轻量级 Web 项目</strong>。</p>
<p>为了帮助大家学习 Svelte,我同时搭建了 Svelte 最新的中文文档站点。</p>
<p>如果需要进阶学习,也可以入手我的小册《Svelte 开发指南》,语法篇、实战篇、原理篇三大篇章带你系统掌握 Svelte!</p>
<p>欢迎围观我的“网页版朋友圈”、加入“冴羽·成长陪伴社群”,踏上“前端大佬成长之路”。</p>
<h2 id="仅服务端模块">仅服务端模块</h2>
<p>SvelteKit 会像一个好朋友一样,保守您的秘密。在同一个代码仓库中编写后端和前端代码时,很容易不小心将敏感数据(例如包含 API 密钥的环境变量)导入到前端代码中。SvelteKit 提供了一种完全防止这种情况发生的方法:仅服务端模块(server-only modules)。</p>
<h3 id="私有环境变量">私有环境变量</h3>
<p><code>$env/static/private</code> 和 <code>$env/dynamic/private</code> 模块只能导入到仅在服务端上运行的模块中,例如 <code>hooks.server.js</code> 或 <code>+page.server.js</code>。</p>
<h3 id="仅服务端工具">仅服务端工具</h3>
<p><code>$app/server</code> 模块包含一个 <code>read</code> 函数,用于从文件系统读取资源,同样只能被服务端运行的代码导入。</p>
<h3 id="您的模块">您的模块</h3>
<p>您可以通过两种方式使您的模块成为仅服务端模块:</p>
<ul>
<li>在文件名中添加 <code>.server</code>,例如 <code>secrets.server.js</code></li>
<li>将它们放在 <code>$lib/server</code> 中,例如 <code>$lib/server/secrets.js</code></li>
</ul>
<h3 id="工作原理">工作原理</h3>
<p>任何时候,当您有公开的代码,导入仅服务端代码时(无论是直接还是间接)...</p>
<pre><code class="language-js">// @errors: 7005
/// file: $lib/server/secrets.js
export const atlantisCoordinates = [
        /* 已编辑 */
];
</code></pre>
<pre><code class="language-js">// @errors: 2307 7006 7005
/// file: src/routes/utils.js
export { atlantisCoordinates } from '$lib/server/secrets.js';

export const add = (a, b) =&gt; a + b;
</code></pre>
<pre><code class="language-html">/// file: src/routes/+page.svelte
&lt;script&gt;
        import { add } from './utils.js';
&lt;/script&gt;
</code></pre>
<p>...SvelteKit 将报错:</p>
<pre><code>Cannot import $lib/server/secrets.js into public-facing code:
- src/routes/+page.svelte
- src/routes/utils.js
    - $lib/server/secrets.js
</code></pre>
<p>尽管公开代码 — <code>src/routes/+page.svelte</code> — 只使用了 <code>add</code> 导出而没有使用秘密的 <code>atlantisCoordinates</code> 导出,秘密代码也可能最终出现在浏览器下载的 JavaScript 中,因此这个导入链被认为是不安全的。</p>
<p>此功能也适用于动态导入,甚至是像 <code>await import(`./${foo}.js`)</code> 这样的插值导入,只有一个小注意点:在开发过程中,如果公开代码和仅服务端模块之间存在两个或更多的动态导入,则在第一次加载代码时不会检测到非法导入。</p>
<blockquote>
<p>[!NOTE] 像 Vitest 这样的单元测试框架不区分仅服务端代码和公开代码。因此,当运行测试时,非法导入检测会被禁用,这由 <code>process.env.TEST === 'true'</code> 决定。</p>
</blockquote>
<h3 id="进一步阅读">进一步阅读</h3>
<ul>
<li>教程:环境变量</li>
</ul>
<h2 id="快照">快照</h2>
<p>临时的 DOM 状态 — 比如侧边栏的滚动位置、<code>&lt;input&gt;</code> 元素的内容等 — 在从一个页面导航到另一个页面时会被丢弃。</p>
<p>例如,如果用户填写了一个表单但在提交之前离开并返回,或者用户刷新页面,他们填写的值将会丢失。在需要保留这些输入的情况下,您可以创建一个 DOM 状态的<em>快照</em>,当用户返回时可以恢复这个状态。</p>
<p>要实现这一点,从 <code>+page.svelte</code> 或 <code>+layout.svelte</code> 中导出一个带有 <code>capture</code> 和 <code>restore</code> 方法的 <code>snapshot</code> 对象:</p>
<pre><code class="language-svelte">&lt;!--- file: +page.svelte ---&gt;
&lt;script&gt;
let comment = $state('');

/** @type {import('./$types').Snapshot&lt;string&gt;} */
export const snapshot = {
    capture: () =&gt; comment,
    restore: (value) =&gt; comment = value
};
&lt;/script&gt;

&lt;form method="POST"&gt;
&lt;label for="comment"&gt;评论&lt;/label&gt;
&lt;textarea id="comment" bind:value={comment} /&gt;
&lt;button&gt;发表评论&lt;/button&gt;
&lt;/form&gt;
</code></pre>
<p>当您离开这个页面时,<code>capture</code> 函数会在页面更新之前立即被调用,返回的值会与浏览器历史栈中的当前记录关联。如果您返回此页面,<code>restore</code> 函数会在页面更新后立即被调用,并传入存储的值。</p>
<p>数据必须是可以序列化为 JSON 的,这样它才能被保存到 <code>sessionStorage</code> 中。这样就可以在页面重新加载时,或者用户从其他网站返回时恢复状态。</p>
<blockquote>
<p>[!NOTE] 避免从 <code>capture</code> 返回非常大的对象 — 一旦被捕获,对象将在会话期间保留在内存中,在极端情况下可能会因太大而无法保存到 <code>sessionStorage</code> 中。</p>
</blockquote>
<h2 id="svelte-中文文档">Svelte 中文文档</h2>
<p>点击查看中文文档:</p>
<ol>
<li>SvelteKit 仅服务端模块</li>
<li>SvelteKit 快照</li>
</ol>
<p>系统学习 Svelte,欢迎入手小册《Svelte 开发指南》。语法篇、实战篇、原理篇三大篇章带你系统掌握 Svelte!</p>
<p>此外我还写过 JavaScript 系列、TypeScript 系列、React 系列、Next.js 系列、冴羽答读者问等 14 个系列文章, 全系列文章目录:https://github.com/mqyqingfeng/Blog</p>
<p>欢迎围观我的“网页版朋友圈”、加入“冴羽·成长陪伴社群”,踏上“前端大佬成长之路”。</p><br><br>
来源:https://www.cnblogs.com/yayujs/p/18806636
頁: [1]
查看完整版本: SvelteKit 最新中文文档教程(17)—— 仅服务端模块和快照