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

Statically generated site, overriding session based info

我的网站基本上是一个静态网站,但我仍然想要身份验证和会话功能。我想象有一种方法可以静态生成网站,但随后会覆盖一些类似你没有登录的消息,以 "user" 身份登录,对吗?更重要的是,它可以与预取一起使用吗?

这部分文档令人困惑:

In other words, any app that involves user sessions or authentication is not a candidate for sapper export.

真正重要的规则是这条:

The basic rule is this: for an app to be exportable, any two users hitting the same page of your app must get the same content from the server.

这并不妨碍您拥有一些代码,对所有用户都相同,但根据客户端会话(例如 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 所承诺的 return 得到解决,以及 (2) 当页面已预取。

如果您打算使用 preload 解析动态内容,重要的是您在服务器中 return 没有任何内容(undefinednull)。否则,如果页面直接被URL访问(比如重新加载同一个页面),那么服务器数据会传递给客户端,preload不会被称为客户端-边。非常微妙的错误。避开它。

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