19

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

根据 Sapper 文档 ( https://sapper.svelte.dev/docs#Getting_started ),我通过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路线时,我看到了:

您的首选语言:空

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

您的首选语言:en

当 localStorage 中没有lang项目时,更改为

您的首选语言:fr

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

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

所以我的问题是:我怎样才能完全跳过服务器初始化?是否可以只在客户端设置商店(在哪里localStorage定义),以便用户选择的语言立即可用?

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

并且在商店重新水化之前出现一闪而过的空文本会搞砸我的应用程序的用户体验,特别是当userLang翻译的值将在整个地方使用时。

因此,对此的任何策略或技巧都绝对值得赞赏。

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

实际上,我更希望这个应用程序根本没有服务器端渲染,但我确实需要 Sapper 提供的所有其他出色功能,例如路由、预取和静态站点构建。

因此,我尝试npx sapper export按照文档运行以生成一个完全静态的站点,以便从等式中删除服务器,但仍然会出现完全相同的问题,即使根本没有使用服务器。

有人对如何配置 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变量立即设置为值 fromlocalStorage或默认值,en正如我在这个简单演示中所打算的那样。没有更多的闪光null,所以它基本上表现得像它只是在这一点上的客户端。

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

4

1 回答 1

18

目前,SSR 是非可选的。SPA 模式存在一个问题——https: //github.com/sveltejs/sapper/issues/383——它的行为与您描述的一样,我们只需要解决它。

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

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

于 2019-06-18T00:32:44.013 回答