Stories

Detail Return Return

SvelteKit 最新中文文檔教程(17)—— 僅服務端模塊和快照 - Stories Detail

前言

Svelte,一個語法簡潔、入門容易,面向未來的前端框架。

從 Svelte 誕生之初,就備受開發者的喜愛,根據統計,從 2019 年到 2024 年,連續 6 年一直是開發者最感興趣的前端框架 No.1

image.png

Svelte 以其獨特的編譯時優化機制著稱,具有輕量級高性能易上手等特性,非常適合構建輕量級 Web 項目

為了幫助大家學習 Svelte,我同時搭建了 Svelte 最新的中文文檔站點。

如果需要進階學習,也可以入手我的小冊《Svelte 開發指南》,語法篇、實戰篇、原理篇三大篇章帶你係統掌握 Svelte!

歡迎圍觀我的“網頁版朋友圈”、加入“冴羽·成長陪伴社羣”,踏上“前端大佬成長之路”。

僅服務端模塊

SvelteKit 會像一個好朋友一樣,保守您的秘密。在同一個代碼倉庫中編寫後端和前端代碼時,很容易不小心將敏感數據(例如包含 API 密鑰的環境變量)導入到前端代碼中。SvelteKit 提供了一種完全防止這種情況發生的方法:僅服務端模塊(server-only modules)。

私有環境變量

$env/static/private$env/dynamic/private 模塊只能導入到僅在服務端上運行的模塊中,例如 hooks.server.js+page.server.js

僅服務端工具

$app/server 模塊包含一個 read 函數,用於從文件系統讀取資源,同樣只能被服務端運行的代碼導入。

您的模塊

您可以通過兩種方式使您的模塊成為僅服務端模塊:

  • 在文件名中添加 .server,例如 secrets.server.js
  • 將它們放在 $lib/server 中,例如 $lib/server/secrets.js

工作原理

任何時候,當您有公開的代碼,導入僅服務端代碼時(無論是直接還是間接)...

// @errors: 7005
/// file: $lib/server/secrets.js
export const atlantisCoordinates = [
    /* 已編輯 */
];
// @errors: 2307 7006 7005
/// file: src/routes/utils.js
export { atlantisCoordinates } from '$lib/server/secrets.js';

export const add = (a, b) => a + b;
/// file: src/routes/+page.svelte
<script>
    import { add } from './utils.js';
</script>

...SvelteKit 將報錯:

Cannot import $lib/server/secrets.js into public-facing code:
- src/routes/+page.svelte
  - src/routes/utils.js
    - $lib/server/secrets.js

儘管公開代碼 — src/routes/+page.svelte — 只使用了 add 導出而沒有使用秘密的 atlantisCoordinates 導出,秘密代碼也可能最終出現在瀏覽器下載的 JavaScript 中,因此這個導入鏈被認為是不安全的。

此功能也適用於動態導入,甚至是像 await import(`./${foo}.js`) 這樣的插值導入,只有一個小注意點:在開發過程中,如果公開代碼和僅服務端模塊之間存在兩個或更多的動態導入,則在第一次加載代碼時不會檢測到非法導入。

[!NOTE] 像 Vitest 這樣的單元測試框架不區分僅服務端代碼和公開代碼。因此,當運行測試時,非法導入檢測會被禁用,這由 process.env.TEST === 'true' 決定。

進一步閲讀

  • 教程:環境變量

快照

臨時的 DOM 狀態 — 比如側邊欄的滾動位置、<input> 元素的內容等 — 在從一個頁面導航到另一個頁面時會被丟棄。

例如,如果用户填寫了一個表單但在提交之前離開並返回,或者用户刷新頁面,他們填寫的值將會丟失。在需要保留這些輸入的情況下,您可以創建一個 DOM 狀態的快照,當用户返回時可以恢復這個狀態。

要實現這一點,從 +page.svelte+layout.svelte 中導出一個帶有 capturerestore 方法的 snapshot 對象:

<!--- file: +page.svelte --->
<script>
  let comment = $state('');

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

<form method="POST">
  <label for="comment">評論</label>
  <textarea id="comment" bind:value={comment} />
  <button>發表評論</button>
</form>

當您離開這個頁面時,capture 函數會在頁面更新之前立即被調用,返回的值會與瀏覽器歷史棧中的當前記錄關聯。如果您返回此頁面,restore 函數會在頁面更新後立即被調用,並傳入存儲的值。

數據必須是可以序列化為 JSON 的,這樣它才能被保存到 sessionStorage 中。這樣就可以在頁面重新加載時,或者用户從其他網站返回時恢復狀態。

[!NOTE] 避免從 capture 返回非常大的對象 — 一旦被捕獲,對象將在會話期間保留在內存中,在極端情況下可能會因太大而無法保存到 sessionStorage 中。

Svelte 中文文檔

點擊查看中文文檔:

  1. SvelteKit 僅服務端模塊
  2. SvelteKit 快照

系統學習 Svelte,歡迎入手小冊《Svelte 開發指南》。語法篇、實戰篇、原理篇三大篇章帶你係統掌握 Svelte!

此外我還寫過 JavaScript 系列、TypeScript 系列、React 系列、Next.js 系列、冴羽答讀者問等 14 個系列文章, 全系列文章目錄:https://github.com/mqyqingfeng/Blog

歡迎圍觀我的“網頁版朋友圈”、加入“冴羽·成長陪伴社羣”,踏上“前端大佬成長之路”。

Add a new Comments

Some HTML is okay.