跳到主要內容

附錄

移轉到 SvelteKit v2

在 GitHub 上編輯此頁面

從 SvelteKit 版本 1 升級到版本 2 應該大多是無縫的。有一些重大變更需要注意,如下所列。您可以使用 npx svelte-migrate@latest sveltekit-2 自動移轉其中一些變更。

我們強烈建議在升級到 2.0 之前升級到最新的 1.x 版本,以便您可以利用有針對性的棄用警告。我們還建議首先更新到 Svelte 4:較新版本的 SvelteKit 1.x 支援它,而 SvelteKit 2.0 需要它。

redirect 和 error 不再由您拋出

以前,您必須自己throwerror(...)redirect(...)返回的值。在 SvelteKit 2 中,不再需要這樣做 — 呼叫函式就足夠了。

import { error } from '@sveltejs/kit'

...
 throw error(500, 'something went wrong');
 error(500, 'something went wrong');

svelte-migrate會自動為您執行這些變更。

如果錯誤或重新導向是在 try {...}區塊內拋出(提示:不要這樣做!),您可以使用從 @sveltejs/kit匯入的 isHttpErrorisRedirect 將它們與意外錯誤區分開來。

設定 cookie 時需要 path

在收到未指定 pathSet-Cookie 標頭時,瀏覽器會 將 cookie 路徑設定 為相關資源的父目錄。此行為並非特別有幫助或直觀,而且經常導致錯誤,因為開發人員預期 cookie 會套用於整個網域。

從 SvelteKit 2.0 開始,您需要在呼叫 cookies.set(...)cookies.delete(...)cookies.serialize(...) 時設定 path,以避免產生歧義。大多數時候,您可能想使用 path: '/',但您可以將其設定為任何您喜歡的內容,包括相對路徑 — '' 表示「目前路徑」,'.' 表示「目前目錄」。

export function load({ cookies }) {
	cookies.set(name, value);
	cookies.set(name, value, { path: '/' });
	return { response }
}

svelte-migrate 會新增註解,標示需要調整的位置。

不再等待頂層承諾

在 SvelteKit 版本 1 中,如果從 load 函式傳回的物件的頂層屬性是承諾,則會自動等待它們。隨著 串流 的引入,此行為變得有點尷尬,因為它會強制您將串流資料巢狀到一個層級。

從版本 2 開始,SvelteKit 不再區分頂層和非頂層承諾。若要回復封鎖行為,請使用 await(適當的話,搭配 Promise.all 以防止瀑布式執行)

// If you have a single promise
export function load({ fetch }) {
	const response = fetch(...).then(r => r.json());
	const response = await fetch(...).then(r => r.json());
	return { response }
}
// If you have multiple promises
export function load({ fetch }) {
	const a = fetch(...).then(r => r.json());
	const b = fetch(...).then(r => r.json());
	const [a, b] = await Promise.all([
	  fetch(...).then(r => r.json()),
	  fetch(...).then(r => r.json()),
	]);
	return { a, b };
}

goto(...) 變更

goto(...) 不再接受外部 URL。若要導覽至外部 URL,請使用 window.location.href = urlstate 物件現在會決定 $page.state,而且必須遵守 App.PageState 介面(如果已宣告)。請參閱 淺層路由 以取得更多詳細資訊。

預設情況下,路徑現在為相對路徑

在 SvelteKit 1 中,app.html 中的 %sveltekit.assets% 在伺服器端渲染期間預設會以相對路徑取代(例如 ...../.. 等,視正在渲染的路徑而定),除非已明確將 paths.relative 設定選項設為 false。從 $app/paths 匯入的 baseassets 也是如此,但前提是 paths.relative 選項已明確設為 true

此不一致性已在版本 2 中修正。路徑會根據 paths.relative 的值,始終為相對路徑或絕對路徑。其預設為 true,因為這會產生更具可攜性的應用程式:如果 base 是應用程式預期以外的內容(例如在 網際網路檔案館 中檢視時),或在建置時未知(例如在部署到 IPFS 等時),較不可能發生中斷。

伺服器擷取不再可追蹤

先前可以追蹤伺服器上 fetch 的網址,以重新執行載入函式。這會造成可能的安全性風險(私人網址外洩),因此已移至 dangerZone.trackServerFetches 設定,該設定現已移除。

preloadCode 參數必須加上 base 前置詞

SvelteKit 揭露兩個函式,preloadCodepreloadData,用於以程式方式載入與特定路徑相關聯的程式碼和資料。在版本 1 中,有一個細微的不一致性 — 傳遞給 preloadCode 的路徑不需要加上 base 路徑(如果已設定),而傳遞給 preloadData 的路徑則需要。

這已在 SvelteKit 2 中修正 — 在這兩種情況下,如果已設定 base,路徑都應該加上 base 前置詞。

此外,preloadCode 現在只接受一個參數,而不是 n 個參數。

已移除 resolvePath

SvelteKit 1 包含一個名為 resolvePath 的函式,可讓您解析路由 ID(例如 /blog/[slug])和一組參數(例如 { slug: 'hello' })成路徑名稱。遺憾的是,回傳值不包含 base 路徑,在設定 base 的情況下會限制其效用。

因此,SvelteKit 2 以一個(命名稍佳)名為 resolveRoute 的函式取代 resolvePath,此函式從 $app/paths 匯入,並考量 base

import { resolvePath } from '@sveltejs/kit';
import { base } from '$app/paths';
import { resolveRoute } from '$app/paths';

const path = base + resolvePath('/blog/[slug]', { slug });
const path = resolveRoute('/blog/[slug]', { slug });

svelte-migrate 會為您執行方法替換,但如果您稍後將結果加上 base 前綴,您需要自行移除。

改善錯誤處理

SvelteKit 1 中的錯誤處理不一致。有些錯誤會觸發 handleError 鉤子,但沒有好的方法來辨別其狀態(例如,辨別 404 和 500 的唯一方法是查看 event.route.id 是否為 null),而其他錯誤(例如對沒有動作的頁面發出 POST 要求的 405 錯誤)根本不會觸發 handleError,但應該觸發。在後一種情況下,如果指定了,產生的 $page.error 會偏離 App.Error 類型。

SvelteKit 2 透過呼叫具有兩個新屬性的 handleError 鉤子來清理此問題:statusmessage。對於從您的程式碼(或您的程式碼呼叫的函式庫程式碼)引發的錯誤,狀態將為 500,訊息將為 Internal Error。雖然 error.message 可能包含不應公開給使用者的敏感資訊,但 message 是安全的。

動態環境變數無法在預先渲染期間使用

$env/dynamic/public$env/dynamic/private 模組提供對執行時間環境變數的存取,而非 $env/static/public$env/static/private 公開的建置時間環境變數。

在 SvelteKit 1 的預先渲染期間,它們是相同的。因此,使用「動態」環境變數的預先渲染頁面實際上是「烘焙」建置時間值,這是錯誤的。更糟的是,如果使用者在導覽到動態渲染頁面之前恰好進入預先渲染頁面,則 $env/dynamic/public 會在瀏覽器中填入這些過時的數值。

因此,在 SvelteKit 2 的預先渲染期間,動態環境變數無法再讀取 — 您應該改用 static 模組。如果使用者進入預先渲染頁面,SvelteKit 會從伺服器要求 $env/dynamic/public 的最新值(預設來自名為 _env.js 的模組 — 這可以使用 config.kit.env.publicModule 設定),而不是從伺服器渲染的 HTML 中讀取。

表單和資料已不再使用:增強回呼

如果您提供回呼給 use:enhance,它將會呼叫一個包含各種有用屬性的物件。

在 SvelteKit 1 中,這些屬性包含 formdata。這些屬性已在一段時間前棄用,取而代之的是 formElementformData,並且已在 SvelteKit 2 中完全移除。

包含檔案輸入的表單必須使用 multipart/form-data

如果表單包含 <input type="file"> 但沒有 enctype="multipart/form-data" 屬性,非 JS 提交將會省略檔案。如果在 use:enhance 提交期間遇到這樣的表單,SvelteKit 2 將會擲回錯誤,以確保您的表單在沒有 JavaScript 的情況下也能正常運作。

產生的 tsconfig.json 更加嚴格

以前,產生的 tsconfig.json 會盡力在您的 tsconfig.json 包含 pathsbaseUrl 時,仍然產生一個有效的設定檔。在 SvelteKit 2 中,驗證更加嚴格,並且當您在 tsconfig.json 中使用 pathsbaseUrl 時會發出警告。這些設定用於產生路徑別名,您應該使用 svelte.config.js 中的 alias 設定 選項,以同時為 bundler 建立對應的別名。

getRequest 不再擲回錯誤

@sveltejs/kit/node 模組匯出用於 Node 環境的輔助函式,包括 getRequest,它會將 Node ClientRequest 轉換為標準 Request 物件。

在 SvelteKit 1 中,如果 Content-Length 標頭超過指定的尺寸限制,getRequest 會擲回錯誤。在 SvelteKit 2 中,錯誤會延後到稍後,也就是在讀取請求主體(如果有)時才會擲回。這能提供更好的診斷和更簡潔的程式碼。

vitePreprocess 不再從 @sveltejs/kit/vite 匯出

由於 @sveltejs/vite-plugin-svelte 現在是對等相依,SvelteKit 2 不再重新匯出 vitePreprocess。您應該直接從 @sveltejs/vite-plugin-svelte 匯入它。

更新相依需求

SvelteKit 2 需要 Node 18.13 或更高版本,以及以下最低相依版本

  • svelte@4
  • vite@5
  • typescript@5
  • @sveltejs/vite-plugin-svelte@3(現在這是 SvelteKit 的peerDependency,之前是直接依賴)
  • @sveltejs/adapter-cloudflare@3(如果你使用這些適配器)
  • @sveltejs/adapter-cloudflare-workers@2
  • @sveltejs/adapter-netlify@3
  • @sveltejs/adapter-node@2
  • @sveltejs/adapter-static@3
  • @sveltejs/adapter-vercel@4

svelte-migrate 會幫你更新 package.json

作為 TypeScript 升級的一部分,產生的 tsconfig.json(你的 tsconfig.json 延伸自此)現在使用 "moduleResolution": "bundler"(TypeScript 團隊推薦,因為它正確地解析類型,來自於在 package.json 中有 exports 地圖的套件)和 verbatimModuleSyntax(取代現有的 importsNotUsedAsValues preserveValueImports 標記,如果你在 tsconfig.json 中有這些,請移除它們。svelte-migrate 會幫你執行此動作)。

前一頁 整合