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

时间:2019-11-21 11:05:16

标签: svelte sapper

我的网站通常是一个静态网站,但我仍希望使用身份验证和会话功能。我想有一种静态生成站点的方法,但是可以覆盖一些类似您未登录的消息,以便以“用户”的身份登录水合作用吧?更重要的是,它可以与预取一起使用吗?

1 个答案:

答案 0 :(得分:0)

这部分文档令人困惑:

  

换句话说,任何涉及用户会话或身份验证的应用程序都不适合用于sapper导出。

真正重要的规则是这一条:

  

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

这并不排除您拥有一些对于所有用户都相同的代码,但是根据客户端会话(例如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函数执行此操作,则将照常预加载此加载。