附錄
移轉到 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 不再由您拋出永久連結
以前,您必須自己throw
從 error(...)
和 redirect(...)
返回的值。在 SvelteKit 2 中,不再需要這樣做 — 呼叫函式就足夠了。
import { error } from '@sveltejs/kit'
...
throw error(500, 'something went wrong');
error(500, 'something went wrong');
svelte-migrate
會自動為您執行這些變更。
如果錯誤或重新導向是在 try {...}
區塊內拋出(提示:不要這樣做!),您可以使用從 @sveltejs/kit
匯入的 isHttpError
和 isRedirect
將它們與意外錯誤區分開來。
設定 cookie 時需要 path永久連結
在收到未指定 path
的 Set-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
會新增註解,標示需要調整的位置。
不再等待頂層承諾permalink
在 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(...) 變更permalink
goto(...)
不再接受外部 URL。若要導覽至外部 URL,請使用 window.location.href = url
。state
物件現在會決定 $page.state
,而且必須遵守 App.PageState
介面(如果已宣告)。請參閱 淺層路由 以取得更多詳細資訊。
預設情況下,路徑現在為相對路徑permalink
在 SvelteKit 1 中,app.html
中的 %sveltekit.assets%
在伺服器端渲染期間預設會以相對路徑取代(例如 .
或 ..
或 ../..
等,視正在渲染的路徑而定),除非已明確將 paths.relative
設定選項設為 false
。從 $app/paths
匯入的 base
和 assets
也是如此,但前提是 paths.relative
選項已明確設為 true
。
此不一致性已在版本 2 中修正。路徑會根據 paths.relative
的值,始終為相對路徑或絕對路徑。其預設為 true
,因為這會產生更具可攜性的應用程式:如果 base
是應用程式預期以外的內容(例如在 網際網路檔案館 中檢視時),或在建置時未知(例如在部署到 IPFS 等時),較不可能發生中斷。
伺服器擷取不再可追蹤永久連結
先前可以追蹤伺服器上 fetch
的網址,以重新執行載入函式。這會造成可能的安全性風險(私人網址外洩),因此已移至 dangerZone.trackServerFetches
設定,該設定現已移除。
preloadCode 參數必須加上 base 前置詞永久連結
SvelteKit 揭露兩個函式,preloadCode
和 preloadData
,用於以程式方式載入與特定路徑相關聯的程式碼和資料。在版本 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
鉤子來清理此問題:status
和 message
。對於從您的程式碼(或您的程式碼呼叫的函式庫程式碼)引發的錯誤,狀態將為 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 中,這些屬性包含 form
和 data
。這些屬性已在一段時間前棄用,取而代之的是 formElement
和 formData
,並且已在 SvelteKit 2 中完全移除。
包含檔案輸入的表單必須使用 multipart/form-data永久連結
如果表單包含 <input type="file">
但沒有 enctype="multipart/form-data"
屬性,非 JS 提交將會省略檔案。如果在 use:enhance
提交期間遇到這樣的表單,SvelteKit 2 將會擲回錯誤,以確保您的表單在沒有 JavaScript 的情況下也能正常運作。
產生的 tsconfig.json 更加嚴格永久連結
以前,產生的 tsconfig.json
會盡力在您的 tsconfig.json
包含 paths
或 baseUrl
時,仍然產生一個有效的設定檔。在 SvelteKit 2 中,驗證更加嚴格,並且當您在 tsconfig.json
中使用 paths
或 baseUrl
時會發出警告。這些設定用於產生路徑別名,您應該使用 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
會幫你執行此動作)。