我最近更新了一個相當複雜的網路應用程式。該應用程式具有 auth、Stripe、i18n、dark/light 模式、PWA 等功能。總體而言,它有大約 30 個頁面和元件,幾乎沒有第三方 npm 套件。
我想指出在將應用程式移轉到 Svelte 5 時我發現非常具有挑戰性的事情。
Svelte 提供的自動遷移腳本可以在終端npx sv migrate svelte-5 中使用這個「one-liner」指令為您完成這項工作(在完成所有必要的更新並安裝之後:「@sveltejs/vite - plugin-svelte」:「^4.0.0」和「svelte」:「^5」)。但我並不推薦這種「錘子」的做法。
使用Ctrl Shift P (Windows/Linux) / Shift Command P (Mac) 逐一檔案、逐個元件地進行操作,並使用Migrate Component to Svelte 5 Syntax 指令而是使用VS Code 指令面板。這樣你就會有更多的控制權。
腳本無法創造奇蹟。將反應式變數宣告升級到 $state() 通常就可以了。但是,腳本可能很難偵測 $: 是否要轉換為 $driven()/$衍生.by(() => {}) 或 $effect(() => {})。
那麼,你猜怎麼著?使用自動遷移腳本,您最終可能會得到大量 run(() => {})。
例如,想像一個使用以下內容的簡化範例:
<script> ... let notext = false; $: if (data.completeDoc == 'NoLangVersion') { notext = true; } $: if (data.completeDoc !== 'NoLangVersion') { notext = false; } </script> ... {#if notext} {data.userPrefferedLang.noTextWarning} {:else} ... {/if} ...
自動遷移腳本將為您提供:
<script> import { run } from 'svelte/legacy'; ... let notext = $state(false); run(() => { if (data.completeDoc == 'NoLangVersion') { notext = true; } }); run(() => { if (data.completeDoc !== 'NoLangVersion') { notext = false; } }); </script>
有一個很好的小警告,run 函數已被棄用。
我猜更好的 Svelte 5 程式碼是這樣的:
<script> ... let notext = $derived.by(() => { if (data.completeDoc == 'NoLangVersion') { return true; } if (data.completeDoc !== 'NoLangVersion') { return false; } }); ... </script>
或如果你的程式碼並不複雜,即使是這樣:
<script> ... let notext = $derived( data.completeDoc == 'NoLangVersion' ? true : false ) ... </script>
原因是腳本無法輕鬆地將程式碼轉換為 $categories.by(() => {}),因此它希望使用更髒的方法 $effect()。但 $effect() 僅在客戶端運行,因此腳本使用已棄用的 run 函數。
現在我們得到了最重要的結論。 $effect() 僅在客戶端運行。所以伺服器上沒有 $effect(),用於預渲染頁面和 SSR。
$effect() 不在伺服器上運作!
Svelte 5 文件中應該要強調這一點。
看這兩個例子:
<script> let a = 1 let b = 2 $: c = a + b </script> {c} // server responds with c == 3
<script> let a = $state(1) let b = $state(2) let c = $state(0) $effect(() => { c = a + b }) </script> {c} // server responds with c == 0
它們不一樣。這帶來了很多挑戰。客戶端在安裝頁面時需要重新評估 c 變數。從伺服器發送的頁面和最終在客戶端進行 DOM 渲染時的頁面看起來會有所不同(SSR、SEO、閃爍問題等)。
因此,請務必嘗試使用 $衍生或 $衍生.by(() => {}) 而不是 $effect()。這會幫你省去很多麻煩。
這與我們被勸阻不要在 SvelteKit 和 SSR 中使用商店時的情況完全相同。
由於 Svelte 5 到來期間給出的範例,您可能會想用 $effect() 取代 SvelteKit 中的 onMount() 。由於已經提到的原因,我暫時不鼓勵這樣做。 onMount 仍然是核心 Svelte 生命週期掛鉤。
另一個令人驚訝的地方是 Svelte 5 非常注意變數值的一致性。如果您將變數作為 prop 傳遞給元件,並稍後在元件中變更此變量,腳本將嘗試使用 $bindable $prop 解決此不一致問題。應通知家長,以便您的應用程式狀態保持一致。
看這個例子:
<script> ... let notext = false; $: if (data.completeDoc == 'NoLangVersion') { notext = true; } $: if (data.completeDoc !== 'NoLangVersion') { notext = false; } </script> ... {#if notext} {data.userPrefferedLang.noTextWarning} {:else} ... {/if} ...
自動遷移腳本將要求您使用具有綁定值的元件,以確保父級可以取回更新的值:
<script> import { run } from 'svelte/legacy'; ... let notext = $state(false); run(() => { if (data.completeDoc == 'NoLangVersion') { notext = true; } }); run(() => { if (data.completeDoc !== 'NoLangVersion') { notext = false; } }); </script>
但也許我們也可以使用更簡單的方法,你猜對了,使用 $衍生():
<script> ... let notext = $derived.by(() => { if (data.completeDoc == 'NoLangVersion') { return true; } if (data.completeDoc !== 'NoLangVersion') { return false; } }); ... </script>
我在遷移過程中發現的一個非常好的功能是我們現在可以使用 CSS :global 和 block。例如,如果您想在 @html 中設定 HTML 元素的樣式,則使用 :global 進行樣式設定是非常必要的。
所以代替這個:
<script> ... let notext = $derived( data.completeDoc == 'NoLangVersion' ? true : false ) ... </script>
你可以用這個:
<script> let a = 1 let b = 2 $: c = a + b </script> {c} // server responds with c == 3
在 Svelte 4 中,如果您想要提供 CSS 類別作為元件的 prop,您可以使用 {$$props.class}:
<script> let a = $state(1) let b = $state(2) let c = $state(0) $effect(() => { c = a + b }) </script> {c} // server responds with c == 0
在 Svelte 5 中你可以使用 class={className}:
// parent svelte file <script> import ComponentBinded from './ComponentBinded.svelte'; import ComponentWithDerived from './ComponentWithDerived.svelte'; let name = $state('John Wick'); </script> <p>Name value in parent: {name}</p> <ComponentBinded bind:name={name} /> <ComponentWithDerived {name} />
當我使用自動合併腳本時,我對應用程式的效能下降感到震驚。有了 Svelte 4,我幾乎獲得了 100% 的成績。直到我手動遷移並仔細考慮如何(主要是如果可能的話如何避免 $effect())後,我的 Lighthouse 分數才再次回到綠色。
遷移到 Svelte 5 的時間比我預期的要長。不過,我還沒有將這個新版本投入生產。 Svelte 5 的更新頻率仍然相當高。
希望我的經驗對其他人有用。
以上是Svelte igration 的經驗與注意事項的詳細內容。更多資訊請關注PHP中文網其他相關文章!