web-dev-qa-db-fra.com

Svelte / Sapper.js - Comment initialiser un magasin avec des données localStorage?

Je viens d'un arrière-plan React mais je passe à Svelte et Sapper pour ma prochaine application afin de lutter contre la taille massive du bundle fourni avec React these Cependant, j'ai du mal à initialiser le magasin de Svelte avec des données récupérées à partir de localStorage.

Selon les documents Sapper ( https://sapper.svelte.dev/docs#Getting_started ), j'ai créé mon projet en exécutant npx degit "sveltejs/sapper-template#rollup" my-app À partir de la ligne de commande. J'ai ensuite installé les dépendances et supprimé le code de démonstration dans le dossier src.

J'ai ensuite créé deux fichiers: src/routes/index.svelte Et src/store/index.js.

Code pour les deux:

src/store/index.js

import {writable} from "svelte/store";

export let userLang;

if(typeof window !== "undefined") {
    userLang = writable(localStorage.getItem("lang") || "en");
} else {
    userLang = writable(null);
}

src/routes/index.svelte

<script>
    import {userLang} from "../store";
</script>

<p>Your Preferred Language: {$userLang}</p>

Lorsque j'exécute l'application et que je frappe la route index, je vois ceci:

Votre langue préférée: null

qui met ensuite à jour et change presque immédiatement

Votre langue préférée: en

lorsqu'il n'y a pas d'élément lang dans localStorage et passe à

Votre langue préférée: en

après avoir explicitement défini localStorage.setItem("lang", "fr") à partir de la console développeur et actualisé.

Je sais que le magasin est d'abord initialisé sur le serveur où window est undefined, puis est réhydraté sur le client. Donc, ce comportement est attendu.

Ma question est donc la suivante: comment ignorer complètement l'initialisation du serveur? Est-il possible de configurer uniquement le magasin sur le client (où localStorage est défini) afin que la langue choisie par l'utilisateur soit immédiatement disponible?

Je ne peux pas par défaut avoir tout en anglais ou dans une autre langue après que l'utilisateur a choisi de changer sa langue préférée. Je ne peux pas non plus obtenir la langue de l'utilisateur à partir du navigateur via navigator.language Lors du chargement initial de la page, car navigator est également undefined sur le serveur.

Et avoir un flash de texte vide avant que le magasin rehytdates ne bousille l'UX pour mon application, surtout quand la valeur de userLang va être utilisée partout avec des traductions.

Donc, toutes les stratégies ou hacks pour cela sont certainement appréciés.

**** Problème plus profond ****

Je préférerais en fait ne pas avoir un rendu côté serveur pour cette application, mais j'ai besoin de toutes les autres excellentes fonctionnalités que Sapper fournit, comme le routage , prélecture et création de site statique.

J'ai donc essayé d'exécuter npx sapper export Selon docs pour générer un site complètement statique dans le but de supprimer le serveur de l'équation, mais le même problème se produit toujours, même s'il existe aucun serveur utilisé du tout.

Quelqu'un a-t-il des conseils sur la façon de configurer Sapper et de désactiver la SSR mais de conserver les autres fonctionnalités?

Je vous remercie!

**** Mise à jour ****

Selon la réponse de Rich Harris, encapsuler le balisage avec {#if process.browser} Fait l'affaire très bien. J'ai donc mis à jour le fichier src/routes/index.svelte Comme ceci:

<script>
    import {userLang} from "../store";
</script>

{#if process.browser}
    <p>Your Preferred Language: {$userLang}</p>
{/if}

et la variable userLang est immédiatement définie avec la valeur de localStorage ou par défaut à en comme je l'ai prévu pour cette démo simple. Il n'y a plus de flash de null, donc il se comporte essentiellement comme côté client uniquement à ce stade.

Je vais travailler à étoffer mon projet et voir s'il y a d'autres problèmes que je rencontre. Jusque-là, je pense que cela résout mon problème.

10
another_one

À l'heure actuelle, la SSR n'est pas facultative. Il y a un problème ouvert pour un mode SPA - https://github.com/sveltejs/sapper/issues/38 - qui se comporterait comme vous le décrivez, nous avons juste besoin de le contourner.

Nous prévoyons également d'avoir un support intégré pour i18n dans une future version: https://github.com/sveltejs/sapper/issues/576

En attendant, vous pouvez le simuler en enveloppant tout votre balisage dans {#if process.browser} - tout ce qui se trouve à l'intérieur ne sera pas rendu par le serveur, mais sera présent dès que JavaScript sera activé.

10
Rich Harris