静态生成的站点,覆盖基于会话的信息



我的网站是一个静态网站,但我仍然想要身份验证和会话功能。我想有一种方法可以静态生成站点,但是然后覆盖诸如您未登录消息之类的内容,以水合的"用户"身份登录,对吗?更重要的是,它会与预取一起使用吗?

文档的这一部分令人困惑:

换句话说,任何涉及用户会话或身份验证的应用都不是工兵导出的候选项。

真正重要的规则是这个:

基本规则是这样的:要使应用可导出,任何两个用户访问应用的同一页面都必须从服务器获取相同的内容。

这并不妨碍您拥有一些代码,对所有用户都是一样的,但根据客户端会话(例如 localStorage...(或您通常在客户端可以执行的任何操作,其行为会有所不同。

例如,你可以在应用中的任何位置有这样的代码:

<script>
  const isServer = typeof window === 'undefined'
  const getUserInfo = async page => {
    if (isServer) {
      // on server, returns a promise that never resolves, to always
      // render as "loading" (adjust to your needs)
      return new Promise()
    }
    // on client, resolve from localStorage, HTTP request, or whatever
    return loadUser(page)
  }
</script>
{#await getUserInfo()}
  <div>Loading...</div>
{:then userInfo}
  {#if userInfo && userInfo.userId != null}
    <div>Logged in as {userInfo.username}</div>
  {:else}
    <a href="/login">Log in</a>
  {/if}
{:catch err}
  <div>Oops: {err}</div>
{/await}

显然,这不会被预取(Sapper 不会分析您的代码的作用(。

但是,您也可以从 preload ,使用如下所示的内容:

<script context="module">
  import { loadUser } from './api'
  const isServer = typeof window === 'undefined'
  export const preload = async page => {
    // if preload returns nothing on the server, then it will be called
    // again in the client (otherwise the client will be passed the preloaded
    // object and preload could be skipped in the client -- see bellow)
    if (isServer) return null
    const { data } = await loadUser(page)
    return { user: data }
  }
</script>
<script>
  // our user from preload
  export let user
</script>
{#if user && !user.anonymous}
  <div>Hello, {user.name}</div>
{:else}
  <a href="/login">Log in</a>
{/if}

这将具有以下效果:(1( 推迟页面的呈现,直到解决 preload 返回的承诺,以及 (2( 在预取页面时开始解析所述用户信息。

如果您打算使用 preload 来解析动态内容,请务必在服务器中不返回任何内容(undefinednull(。否则,如果通过 URL 直接访问页面(例如,如果重新加载同一页面(,则服务器数据将传递到客户端,并且不会调用preload客户端。非常微妙的错误。避免它。

因此,总而言之,服务器中preload返回的任何内容都将包含在您的静态站点中(因此,可公开访问(。但是,您仍然可以在客户端中管理会话和加载动态内容。如果从 preload 函数执行此操作,则此加载将像往常一样预取。

最新更新