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.

Другие вопросы по тегам