Svelte/Sapper.js - Как инициализировать хранилище с данными localStorage?
Я работаю в React, но переключаюсь на Svelte и Sapper для моего следующего приложения, чтобы бороться с огромным размером пакета, который поставляется с React в наши дни. Однако у меня возникают проблемы при инициализации хранилища Svelte с данными, полученными из localStorage.
Согласно документам Sapper ( https://sapper.svelte.dev/docs), я создал свой проект, запустив npx degit "sveltejs/sapper-template#rollup" my-app
из командной строки. Затем я установил зависимости и удалил демонстрационный код в src
папка.
Затем я создал два файла: src/routes/index.svelte
а также src/store/index.js
,
Код для обоих:
ЦСИ / магазин /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 / маршруты /index.svelte
<script>
import {userLang} from "../store";
</script>
<p>Your Preferred Language: {$userLang}</p>
Когда я запускаю приложение и нажимаю index
маршрут, я вижу это:
Ваш предпочтительный язык: ноль
который затем почти сразу же обновляется и изменяется на
Ваш предпочтительный язык: en
когда нет lang
элемент в localStorage и изменяется на
Ваш предпочитаемый язык: fr
после явной настройки localStorage.setItem("lang", "fr")
из консоли разработчика и обновления.
Я знаю, что магазин инициализируется на сервере первым, где window
является undefined
и затем регидратируется на клиенте. Так что это поведение ожидается.
Итак, мой вопрос: как я могу полностью пропустить инициализацию сервера? Можно ли настроить только магазин на клиенте (где localStorage
определяется) так что выбранный пользователем язык сразу доступен?
Я не могу по умолчанию иметь все на английском или любом другом языке после того, как пользователь решил изменить предпочитаемый язык. Я также не могу получить язык пользователя из браузера через navigator.language
на начальной загрузке страницы либо с navigator
является undefined
на сервере, а также.
И появление вспышки пустого текста до того, как магазин заменится, испортит UX для моего приложения, особенно когда значение userLang
будет использоваться повсюду с переводами.
Так что любые стратегии или хаки для этого, безусловно, приветствуются.
**** Более глубокий выпуск ****
Я бы на самом деле предпочел бы вообще не иметь серверного рендеринга для этого приложения, но мне нужны все другие замечательные функции, которые предоставляет Sapper, такие как маршрутизация, предварительная выборка и статическое построение сайтов.
Итак, я попытался запустить npx sapper export
в соответствии с документами для создания полностью статического сайта в попытке удалить сервер из уравнения, но точно такая же проблема все еще возникает, даже если сервер вообще не используется.
Кто-нибудь есть какие-либо советы о том, как настроить Sapper и отключить SSR, но сохранить другие функции?
Спасибо!
**** Обновление ****
Согласно ответу Рича Харриса, завернуть разметку {#if process.browser}
делает трюк просто отлично. Итак, я обновил src/routes/index.svelte
файл вроде так:
<script>
import {userLang} from "../store";
</script>
{#if process.browser}
<p>Your Preferred Language: {$userLang}</p>
{/if}
и userLang
переменная сразу устанавливается со значением из localStorage
или по умолчанию en
как я и предполагал для этого простого демо. Нет больше вспышки null
так что по сути он ведет себя так, как если бы он был только на стороне клиента.
Я буду работать над реализацией своего проекта и посмотрю, не возникнет ли еще каких-либо проблем, с которыми я столкнусь. До тех пор, я думаю, что это решает мою проблему.
1 ответ
В настоящее время SSR не является обязательным. Есть проблема, открытая для режима SPA - https://github.com/sveltejs/sapper/issues/383 - которая будет вести себя так, как вы описываете, нам просто нужно обойти ее.
Мы также планируем встроенную поддержку i18n в следующем выпуске: https://github.com/sveltejs/sapper/issues/576
В то же время, вы можете подделать его, завернув всю разметку в {#if process.browser}
- все, что находится внутри, не будет отображаться на сервере, но будет присутствовать, как только включится JavaScript.