Heim > Web-Frontend > js-Tutorial > Erfahrungen und Vorbehalte der schlanken Migration

Erfahrungen und Vorbehalte der schlanken Migration

Barbara Streisand
Freigeben: 2024-11-04 10:46:30
Original
882 Leute haben es durchsucht

Experiences and Caveats of Svelte igration

Ich habe kürzlich eine ziemlich komplexe Webanwendung aktualisiert. Die Anwendung verfügt über Funktionen wie Authentifizierung, Stripe, i18n, Dunkel-/Hellmodus, PWA usw. Insgesamt verfügt sie über etwa 30 Seiten und Komponenten, fast ohne npm-Pakete von Drittanbietern.

Ich möchte darauf hinweisen, was ich bei der Migration der App auf Svelte 5 als ziemliche Herausforderung empfand.

Skripthammer für die automatische Migration

Das von Svelte bereitgestellte automatische Migrationsskript kann die Arbeit mit diesem „einzeiligen“ Befehl im Terminal npx sv migrate svelte-5 für Sie erledigen (nachdem Sie alle erforderlichen Updates und Installationen durchgeführt haben: „@sveltejs/vite -plugin-svelte“: „^4.0.0“ und „svelte“: „^5“). Ich empfehle diesen „Hammer“-Ansatz jedoch nicht.

Gehen Sie Datei für Datei, Komponente für Komponente mit Strg Umschalt P (Windows/Linux) / Umschaltbefehl P (Mac) und verwenden Sie den Befehl „Komponente in Svelte 5-Syntax migrieren“. stattdessen die VS-Code-Befehlspalette. Auf diese Weise haben Sie mehr Kontrolle.

Veraltete run()-Überraschung

Das Skript kann keine Wunder vollbringen. Das Upgrade reaktiver Variablendeklarationen auf $state() ist normalerweise in Ordnung. Allerdings kann es für das Skript schwierig sein zu erkennen, ob $: in $derived()/$derived.by(() => {}) oder $effect(() => {}) konvertiert werden soll.

Also, wissen Sie was? Mit dem Auto-Migration-Skript kann es passieren, dass Sie eine Menge run(() => {}).

erhalten

Stellen Sie sich zum Beispiel als vereinfachtes Beispiel Folgendes vor:

<script>
...
   let notext = false;
   $: if (data.completeDoc == 'NoLangVersion') {
      notext = true;
   }
   $: if (data.completeDoc !== 'NoLangVersion') {
      notext = false;
   }
</script>

...
{#if notext}
   {data.userPrefferedLang.noTextWarning}
{:else}
...
{/if}
...
Nach dem Login kopieren
Nach dem Login kopieren

Das automatische Migrationsskript gibt Ihnen Folgendes:

<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>
Nach dem Login kopieren
Nach dem Login kopieren

mit einer netten kleinen Warnung, dass die Ausführungsfunktion veraltet ist.

Der bessere Svelte 5-Code wäre meiner Meinung nach dieser:

<script>
...
    let notext = $derived.by(() => {
        if (data.completeDoc == 'NoLangVersion') {
            return  true;
        }
        if (data.completeDoc !== 'NoLangVersion') {
            return false;
        }
    });
...
</script>
Nach dem Login kopieren
Nach dem Login kopieren

oder wenn Ihr Code nicht wirklich kompliziert ist, auch so:

<script>
...
    let notext = $derived(
        data.completeDoc == 'NoLangVersion' 
        ? 
        true
        :
        false
        ) 
...
</script>
Nach dem Login kopieren
Nach dem Login kopieren

Der Grund dafür ist, dass das Skript Code nicht einfach in $derived.by(() => {}) umwandeln kann, daher würde es gerne einen schmutzigeren Ansatz mit $effect() verwenden. Da $effect() jedoch nur clientseitig ausgeführt wird, verwendet das Skript stattdessen die veraltete Ausführungsfunktion.

Vermeiden Sie $effect, wenn Sie können

Jetzt kommen wir zum wichtigsten Imbiss. Das heißt, dass $effect() nur clientseitig ausgeführt wird. Also kein $effect() auf dem Server, für das Vorrendern von Seiten und SSR.

$effect() LÄUFT NICHT AUF DEM SERVER!

Dies sollte in der Svelte 5-Dokumentation wirklich hervorgehoben werden.

Sehen Sie sich diese beiden Beispiele an:

<script>
let a = 1
let b = 2

$: c = a + b
</script>

{c}  // server responds with c == 3
Nach dem Login kopieren
Nach dem Login kopieren
<script>
let a = $state(1)
let b = $state(2)
let c = $state(0)

$effect(() => {
  c = a + b
})
</script>

{c}  // server responds with c == 0
Nach dem Login kopieren
Nach dem Login kopieren

Sie sind nicht gleich. Dies bringt viele Herausforderungen mit sich. Der Client muss die C-Variable beim Mounten der Seite neu bewerten. Die Seite sieht anders aus, wenn sie vom Server gesendet und schließlich auf dem Client DOM-gerendert wird (SSR, SEO, Flimmerprobleme usw.).

Versuchen Sie also immer, $derived oder $derived.by(() => {}) anstelle von $effect() zu verwenden. Es wird Ihnen viel Ärger ersparen.

Es ist ziemlich die gleiche Geschichte wie damals, als uns davon abgeraten wurde, die Geschäfte in SvelteKit und SSR zu nutzen.

$effect vs onMount() in SvelteKit

Dank der Beispiele, die bei der Einführung von Svelte 5 gegeben wurden, könnten Sie versucht sein, onMount() in SvelteKit durch $effect() zu ersetzen. Aus den bereits genannten Gründen würde ich davon vorerst abraten. onMount ist immer noch ein zentraler Svelte-Lebenszyklus-Hook.

$bindable $props Überraschung

Die andere schöne Überraschung ist, dass Svelte 5 auf konsistente Variablenwerte achtet. Wenn Sie einer Komponente eine Variable als Requisite übergeben und diese Variable später in der Komponente ändern, versucht das Skript, diese Inkonsistenz mithilfe von $bindable $prop zu beheben. Die Eltern sollten benachrichtigt werden, damit Ihr App-Status konsistent ist.

Sehen Sie sich dieses Beispiel an:

<script>
...
   let notext = false;
   $: if (data.completeDoc == 'NoLangVersion') {
      notext = true;
   }
   $: if (data.completeDoc !== 'NoLangVersion') {
      notext = false;
   }
</script>

...
{#if notext}
   {data.userPrefferedLang.noTextWarning}
{:else}
...
{/if}
...
Nach dem Login kopieren
Nach dem Login kopieren

Das Autou-Migration-Skript fordert Sie auf, eine Komponente mit gebundenem Wert zu verwenden, um sicherzustellen, dass das übergeordnete Element den aktualisierten Wert zurückerhält:

<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>
Nach dem Login kopieren
Nach dem Login kopieren

Aber vielleicht können wir auch einen ganz einfacheren Weg verwenden, Sie haben es erraten, mit $derived():

<script>
...
    let notext = $derived.by(() => {
        if (data.completeDoc == 'NoLangVersion') {
            return  true;
        }
        if (data.completeDoc !== 'NoLangVersion') {
            return false;
        }
    });
...
</script>
Nach dem Login kopieren
Nach dem Login kopieren

:global { } Block

Eine sehr schöne Funktion, die ich während der Migration gefunden habe, war, dass wir jetzt CSS :global mit Block verwenden können. Das Styling mit :global ist durchaus notwendig, wenn Sie beispielsweise die HTML-Elemente in @html formatieren möchten.

Also stattdessen:

<script>
...
    let notext = $derived(
        data.completeDoc == 'NoLangVersion' 
        ? 
        true
        :
        false
        ) 
...
</script>
Nach dem Login kopieren
Nach dem Login kopieren

Sie können Folgendes verwenden:

<script>
let a = 1
let b = 2

$: c = a + b
</script>

{c}  // server responds with c == 3
Nach dem Login kopieren
Nach dem Login kopieren

Stil als Requisite in Komponenten

Wenn Sie in Svelte 4 eine CSS-Klasse als Requisite für eine Komponente bereitstellen möchten, verwenden Sie {$$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
Nach dem Login kopieren
Nach dem Login kopieren

In Svelte 5 können Sie class={className}:
verwenden

// 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} />
Nach dem Login kopieren

Möglicher Leistungsabfall bei Lighthouse

Als ich das Skript für die automatische Zusammenführung verwendete, war ich schockiert darüber, wie die Leistung meiner App abnahm. Mit Svelte 4 hatte ich fast alle 100 %. Erst nachdem ich manuell migriert und sorgfältig darüber nachgedacht hatte, wie (hauptsächlich, wie man $effect() wenn möglich vermeidet), waren meine Lighthouse-Scores wieder im grünen Bereich.

Letzte Worte

Die Migration auf Svelte 5 dauerte länger als erwartet. Allerdings habe ich diese neue Version immer noch nicht in Produktion gebracht. Die Updates für Svelte 5 kommen immer noch mit recht hoher Häufigkeit.

Ich hoffe, dass meine Erfahrung für andere nützlich sein kann.

Das obige ist der detaillierte Inhalt vonErfahrungen und Vorbehalte der schlanken Migration. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Quelle:dev.to
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Neueste Artikel des Autors
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage