Svelte / Sapper.js - Как инициализировать хранилище данными localStorage?

У меня есть опыт работы с React, но я перехожу на Svelte и Sapper для своего следующего приложения, чтобы бороться с огромным размером пакетов, которые сейчас поставляются с React. Однако у меня возникли проблемы с инициализацией хранилища Svelte данными, полученными из localStorage.

Согласно документации Sapper (https://sapper.svelte.dev/docs#Getting_started) , Я создал свой проект, запустив npx degit "sveltejs/sapper-template#rollup" my-app из командной строки. Затем я установил зависимости и удалил демонстрационный код в папке src.

Затем я создал два файла: src/routes/index.svelte и src/store/index.js.

Код для обоих:

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>

Когда я запускаю приложение и выбираю маршрут index, я вижу следующее:

Ваш предпочтительный язык: null

который затем почти сразу обновляется и меняется на

Ваш предпочтительный язык: en

когда в localStorage нет lang элемента, и меняется на

Ваш предпочтительный язык: fr

После явной установки localStorage.setItem("lang", "fr") в консоли разработчика и обновления.

Я знаю, что хранилище сначала инициализируется на сервере, где window равно undefined, а затем выполняется регидратация на клиенте. Так что такое поведение ожидаемо.

Итак, мой вопрос: как я могу полностью пропустить инициализацию сервера? Можно ли настроить магазин только на клиенте (где определено localStorage), чтобы язык, выбранный пользователем, был доступен сразу же?

Я не могу по умолчанию иметь все на английском или любом другом языке после того, как пользователь решил изменить свой предпочтительный язык. Я также не могу получить язык пользователя из браузера через navigator.language при начальной загрузке страницы, поскольку navigator также undefined на сервере.

И появление вспышки пустого текста до регидратации магазина испортит UX для моего приложения, особенно когда значение userLang будет использоваться повсюду с переводами.

Так что любые стратегии или хаки для этого определенно приветствуются.

**** Более глубокая проблема ****

На самом деле я бы предпочел, чтобы для этого приложения не был вообще рендеринг на стороне сервера, но мне нужны все другие отличные функции, которые предоставляет Sapper, такие как маршрутизация, предварительная выборка и создание статических сайтов.

Поэтому я попытался запустить npx sapper export в соответствии с docs, чтобы создать полностью статический сайт и попытаться удалить сервер из уравнения, но та же проблема все еще возникает, даже если сервер вообще не используется.

Есть ли у кого-нибудь совет, как настроить Sapper и отключить SSR, но сохранить другие функции?

Спасибо!

**** Обновление ****

Согласно ответу Рича Харриса, упаковка разметки с помощью {#if process.browser} отлично справляется. Итак, я обновил src/routes/index.sveltefile вот так:

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

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

И переменная userLang сразу устанавливается со значением от localStorage или по умолчанию на en, как я задумал для этой простой демонстрации. Вспышки null больше нет, так что, по сути, он ведет себя как клиентская только в этот момент.

Я буду работать над конкретизацией своего проекта и посмотрю, с какими еще проблемами я столкнусь. А пока, думаю, это решит мою проблему.


person another_one    schedule 17.06.2019    source источник


Ответы (1)


В настоящее время SSR не является обязательным. Открыта проблема для режима SPA - https://github.com/sveltejs/sapper/issues/383 - это будет вести себя так, как вы описываете, нам просто нужно решить эту проблему.

Мы также планируем иметь встроенную поддержку i18n в следующем выпуске: https://github.com/sveltejs/sapper/issues/576

А пока вы можете подделать это, обернув всю свою разметку в {#if process.browser} - все, что находится внутри, не будет отображаться на сервере, но будет присутствовать, как только начнется JavaScript.

person Rich Harris    schedule 18.06.2019
comment
Спасибо за ответ! Я обязательно буду следить за этими проблемами и попытаюсь обернуть разметку в блок if, как вы сказали. А также спасибо за то, что Svelte делает все вокруг. Я знаю, что со временем проект будет становиться все лучше и лучше - person another_one; 18.06.2019
comment
Мой токен хранится в localStorage, как мне обойти это с помощью сапера? - person chovy; 08.04.2020
comment
Стоит отметить, что проверка process.browser также работает в обычном JS-коде, а не только в шаблонах. Спасибо! - person Daniel Veihelmann; 13.04.2020
comment
process.browser работает в моей среде сборки. но при экспорте не работает. - person Ilse Van Dommelen; 07.08.2020