Svelte/Sapper.js - 如何使用 localStorage 数据初始化存储?

Svelte/Sapper.js - How to initialize store with localStorage data?

我有 React 背景,但我正在为我的下一个应用程序切换到 Svelte 和 Sapper,以应对这些天 React 带来的庞大的包大小。但是,我在使用从 localStorage 检索到的数据初始化 Svelte 的存储时遇到了问题。

根据 Sapper 文档 (https://sapper.svelte.dev/docs#Getting_started),我从命令行 运行ning npx degit "sveltejs/sapper-template#rollup" my-app 创建了我的项目。然后我安装了依赖项并删除了 src 文件夹中的演示代码。

然后我创建了两个文件:src/routes/index.sveltesrc/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 路由时,我看到:

Your Preferred Language: null

然后几乎立即更新并更改为

Your Preferred Language: en

当localStorage中没有lang项时,变为

Your Preferred Language: fr

从开发者控制台明确设置 localStorage.setItem("lang", "fr") 并刷新后。

我知道商店首先在服务器上初始化,其中 windowundefined,然后在客户端上重新水化。所以这种行为是意料之中的。

所以我的问题是:如何才能完全跳过服务器初始化?是否可以仅在客户端设置商店(其中定义了 localStorage)以便用户选择的语言立即可用?

在用户选择更改他们的首选语言后,我不能默认所有内容都是英语或任何其他语言。我也无法在初始页面加载时通过 navigator.language 从浏览器获取用户语言,因为 navigator 在服务器上也是 undefined

并且在商店再水化之前出现一闪而过的空白文本会搞砸我的应用程序的用户体验,尤其是当 userLang 的值将被用于翻译的所有地方时。

因此,我们非常感谢任何与此相关的策略或技巧。

**** 更深层次的问题 ****

我实际上更希望为这个应用程序提供服务器端渲染,但我确实需要 Sapper 提供的所有其他优秀功能,如路由、预取、和静态网站建设。

所以我尝试 运行ning npx sapper export 根据 docs 生成一个完全静态的站点,以努力从等式中删除服务器,但仍然存在完全相同的问题发生,即使根本没有服务器被使用。

有没有人对如何配置 Sapper 并关闭 SSR 但保留其他功能有任何建议?

谢谢!

**** 更新 ****

根据 Rich Harris 的回答,用 {#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 的 flash,因此此时它基本上表现得像是客户端。

我会努力充实我的项目,看看是否还有其他问题。到那时,我认为这解决了我的问题。

目前SSR为non-optional。 SPA 模式有一个未解决的问题 — https://github.com/sveltejs/sapper/issues/383 — 其行为如您所述,我们只需要解决它。

我们还计划在未来的版本中 built-in 支持 i18n:https://github.com/sveltejs/sapper/issues/576

与此同时,您可以通过将所有标记包装在 {#if process.browser} 中来伪造它 — 里面的任何内容都不会被服务器呈现,但会在 JavaScript 启动后立即出现。