Skip to content

Migration du frontend vers Svelte 5 - #16

Merged
Wasabules merged 1 commit into
mainfrom
svelte-5
Sep 5, 2026
Merged

Migration du frontend vers Svelte 5#16
Wasabules merged 1 commit into
mainfrom
svelte-5

Conversation

@Wasabules

Copy link
Copy Markdown
Owner

Svelte 3.59 → 5.57, Vite 3.2 → 8.2, @sveltejs/vite-plugin-svelte 1.4 → 7.3,
svelte-check 2.10 → 4.7, TypeScript 4.9 → 5.9. svelte-preprocess disparaît :
vitePreprocess délègue TypeScript à l'esbuild de Vite, ce qui laisse une seule
chaîne TS au lieu de deux susceptibles de diverger sur le tsconfig.

Ce que la migration a demandé

Peu de choses, et c'était mesurable à l'avance. Le seul changement d'API forcé
est main.ts : new App({ target }) est refusé, mount() le remplace. En mode
legacy les 11 export let, 23 $:, 4 {@const} et le <slot> compilent
inchangés, et le projet n'utilisait aucune des API retirées ($$props,
$$restProps, $$slots, beforeUpdate/afterUpdate, createEventDispatcher,
svelte:component, bind: sur composant).

Deux valeurs qui auraient cessé de se mettre à jour

Svelte 3 recalculait chaque expression du markup à chaque mise à jour, donc une
fonction appelée depuis le markup qui lisait de l'état d'instance était
réexécutée assez souvent pour paraître correcte. Svelte 5 ne suit que ce que
l'expression lit, et enveloppe l'appel dans untrack() — une lecture à
l'intérieur de la fonction appelée est donc explicitement ignorée.

Vérifié sur la sortie du compilateur plutôt que supposé :

{label(n)}       ->  template_effect([() => (read(n), untrack(() => label(n)))])
{label(n, $t)}   ->  template_effect([() => (read(n), $t(), untrack(...))])

Deux occurrences dans l'arbre, corrigées en passant la dépendance en paramètre :

  • Settings.svelte{estimateMessagesForSize(maxDbSize)} lisait $_ dans
    son corps. Changer de langue ne change pas maxDbSize, donc l'estimation
    serait restée dans l'ancienne langue jusqu'à ce que la taille bouge.
  • LogViewer.sveltegroupColor() lisait $groupBy. Une clé de groupe
    survivant à un changement de critère aurait gardé son ancienne couleur.

Aucun des deux n'était un bug sous Svelte 3 : ils fonctionnaient par accident.

Accessibilité : les 5 avertissements du nouveau compilateur

Un seul était un vrai défaut fonctionnel :

  • ToastContainer — le toast était à la fois une région role="alert" et un
    contrôle, avec on:click, on:keydown et un tabindex sur une région qui n'a
    pas vocation à recevoir le focus. Les technologies d'assistance annonçaient
    le message sans jamais proposer de le fermer.
    La région annonce désormais, et
    un vrai <button aria-label> ferme — libellé pris sur common.close, déjà
    traduit dans les 8 locales.

Les autres sont de la sémantique manquante :

  • Settings et TLSConfig : role="dialog" sans tabindex, donc le dialogue
    ne pouvait pas recevoir le focus.
  • Settings : l'overlay de confirmation du chiffrement n'avait ni rôle ni
    sémantique de dialogue, contrairement aux autres modales du projet.
  • FilterBar : le on:click|stopPropagation du <label> était du code mort
    — aucun ancêtre du label ne porte de handler click (le bouton du dropdown en
    est un frère, le backdrop est au niveau racine). Retiré.

Les deux formes de svelte-ignore (tirets et underscores) restent honorées par
Svelte 5 — vérifié au compilateur — donc les 8 directives existantes tiennent, et
n'ont pas été silencieusement désactivées par la migration.

Retombées

Avant Après
npm audit 12 (7 modérées, 5 élevées) 2 modérées
Bundle JS 222 kB / 67,2 kB gzip 208 kB / 65,0 kB gzip
Arbre de dépendances plusieurs centaines 80 paquets

Les 2 avis restants sont un esbuild imbriqué dans svelte-i18n, dont le seul
correctif proposé est une rétrogradation cassante de svelte-i18n.

La CI passe à Node 22 : Vite 8 exige ^20.19 || >=22.12, et épingler le
majeur évite de dépendre de la 20.x que le runner résout ce jour-là.

Vérifications

svelte-check : 0 erreur, 0 avertissement avec --fail-on-warnings.
wails build, go vet et go test -race passent. models.ts est la sortie
déterministe de Wails 2.15, committée pour qu'elle cesse de reparaître à chaque
build.

…té latents

Svelte 3.59 → 5.57, Vite 3.2 → 8.2, @sveltejs/vite-plugin-svelte 1.4 → 7.3,
svelte-check 2.10 → 4.7, TypeScript 4.9 → 5.9. svelte-preprocess disparaît :
vitePreprocess du plugin délègue TypeScript à l'esbuild de Vite, ce qui laisse
une seule chaîne TS au lieu de deux susceptibles de diverger sur le tsconfig.

Le seul changement d'API forcé est main.ts : `new App({ target })` est refusé
(component_api_invalid_new), mount() le remplace. En mode legacy, les 11
`export let`, 23 `$:`, 4 `{@const}` et le `<slot>` compilent inchangés, et le
projet n'utilisait aucune des API retirées ($$props, $$restProps, $$slots,
beforeUpdate/afterUpdate, createEventDispatcher, svelte:component, bind: sur
composant).

Deux valeurs qui auraient cessé de se mettre à jour
---------------------------------------------------
Svelte 3 recalculait chaque expression du markup à chaque mise à jour, donc une
fonction appelée depuis le markup qui lisait de l'état d'instance était
réexécutée assez souvent pour paraître correcte. Svelte 5 ne suit que ce que
l'EXPRESSION lit, et enveloppe l'appel lui-même dans untrack() — une lecture à
l'intérieur de la fonction appelée est donc explicitement ignorée. Vérifié sur
la sortie du compilateur plutôt que supposé :

  expression `{label(n)}`      -> template_effect([() => (read(n), untrack(() => label(n)))])
  expression `{label(n, $t)}`  -> template_effect([() => (read(n), $t(), untrack(...))])

Deux occurrences dans l'arbre, toutes deux corrigées en passant la dépendance
en paramètre :

- Settings.svelte : {estimateMessagesForSize(maxDbSize)} lisait $_ dans son
  corps. Changer de langue ne change pas maxDbSize, donc l'estimation serait
  restée dans l'ancienne langue jusqu'à ce que la taille bouge.
- LogViewer.svelte : groupColor() lisait $groupBy. Une clé de groupe survivant
  à un changement de critère aurait gardé son ancienne couleur.

Aucun des deux n'était un bug sous Svelte 3 : ils fonctionnaient par accident.

Accessibilité : les 5 avertissements du nouveau compilateur
------------------------------------------------------------
- ToastContainer : le toast était à la fois une région role="alert" et un
  contrôle, avec on:click, on:keydown et un tabindex sur une région qui n'a pas
  vocation à recevoir le focus. Les technologies d'assistance annonçaient donc
  le message sans jamais proposer de le fermer. La région annonce désormais, et
  un vrai <button aria-label> ferme — libellé pris sur common.close, déjà
  traduit dans les 8 locales.
- Settings et TLSConfig : role="dialog" sans tabindex, donc le dialogue ne
  pouvait pas recevoir le focus. tabindex="-1" ajouté.
- Settings : l'overlay de confirmation du chiffrement n'avait ni rôle ni
  sémantique de dialogue, contrairement aux autres modales du projet. Il devient
  role="presentation" avec, à l'intérieur, une carte role="dialog" aria-modal
  reliée à son titre.
- FilterBar : le on:click|stopPropagation du <label> était du code mort — aucun
  ancêtre du label ne porte de handler click (le bouton du dropdown en est un
  frère, le backdrop est au niveau racine). Retiré, avec le svelte-ignore
  devenu inutile.

Les deux formes de svelte-ignore (tirets et underscores) restent honorées par
Svelte 5 — vérifié au compilateur —, donc les 8 directives existantes tiennent.

Retombées
---------
npm audit passe de 12 vulnérabilités (7 modérées, 5 élevées) à 2 modérées, un
esbuild imbriqué dans svelte-i18n dont le seul correctif proposé est une
rétrogradation cassante de svelte-i18n. Le bundle passe de 222 à 208 kB
(67,2 → 65,0 kB gzip) et l'arbre de dépendances de plusieurs centaines de
paquets à 80.

La CI passe à Node 22 : Vite 8 exige ^20.19 || >=22.12, et épingler le majeur
évite de dépendre de la 20.x que le runner résout ce jour-là.

svelte-check : 0 erreur, 0 avertissement avec --fail-on-warnings.
wails build, go vet et go test -race passent. models.ts est la sortie
déterministe de Wails 2.15, committée pour qu'elle cesse de reparaître à chaque
build.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant