【问题标题】:How can I fix localStorage error in sapper/svelte如何修复 sapper/svelte 中的 localStorage 错误
【发布时间】:2021-04-12 00:11:25
【问题描述】:
import { writable } from 'svelte/store';

/** Read the current token from LocalStorage on boot */
const token = writable(localStorage.getItem('token'));
/** Store the token in LocalStorage whenever it´s updated */
token.subscribe((val) => {
  if (!localStorage) return;

  if (!val) {
    return localStorage.removeItem('token');
  }

  localStorage.setItem('token', val);
});

export default token;

当我运行 npm run dev 时,我仍然收到一个错误,即 localStorage 在 sapper 中未定义

【问题讨论】:

标签: svelte sapper


【解决方案1】:

在 Sapper 中,您的代码将在浏览器和 Node for SSR 中运行。真正的 Node,甚至不是像 jsdom 之类的模拟浏览器环境。 (不一定是“会”,实际上是“可能”,因为只有浏览器请求的第一个页面会在服务器端呈现,但仍然需要确保所有代码都支持两者)。

在 Node 中,许多浏览器 API,如 localStorage,不可用。

在 JS 中,你不能像这样测试变量的存在:

if (!localStorage) ...

如果该变量不存在,您会因此而崩溃。测试变量是否存在的安全方法如下:

if (typeof localStorage === 'undefined') ...

因此,通过像这样重写您的商店,使您的代码浏览器 + 节点兼容:

const createBrowserTokenStore = () => {
  const store = writable(localStorage.getItem('token'))
  
  // Store the token in LocalStorage whenever it´s updated
  store.subscribe((val) => {
    if (!localStorage) return
    if (!val) return localStorage.removeItem('token')
    localStorage.setItem('token', val)
  })

  return store
}

// just enough to not crash in Node
const createNodeTokenStore = () => writable(null)

export const token = typeof localStorage === 'undefined'
  ? createNodeTokenStore()
  : createBrowserTokenStore()

请注意,即使在 SSR 上下文(即 Node)中,浏览器代码也会运行。页面进行 SSR 时的准确操作顺序如下:

  • 页面 HTML 在 Node 中呈现,组件使用 ssr: true 编译选项编译——也就是说,组件仅用于一次渲染 HTML 字符串

  • HTML 被发送到浏览器

  • 浏览器会按原样显示您的页面

  • 在后台,JS被加载并执行

  • 您的 Svelte 组件将使用 hydratable 选项重新运行,这意味着它们将尝试回收现有的 DOM 元素,而不是无条件地创建它们

  • 您的页面现在是交互式的,但在获取 HTML 和加载 JS 之间的短暂(或不那么短)间隔内已经很好看

我想说明的是,您的 JS 将在浏览器中运行,即使该页面是由 SSR 呈现的,并且结果将替换 SSR 通行证产生的内容。如果客户端 JS 组件产生的 DOM 元素与服务器完全不同,那么 Svelte 将覆盖。

这意味着,在这种情况下,只提供最低限度让代码不会在 Node 中崩溃是可以接受的。如果您可以生成接近浏览器也将呈现的结果,那当然更好。 (另一种选择是调整您的代码,以便服务器在仅浏览器的情况下呈现类似“正在加载...”的内容)。

【讨论】:

    猜你喜欢
    • 2020-06-06
    • 2020-05-10
    • 1970-01-01
    • 1970-01-01
    • 2019-11-24
    • 2020-09-04
    • 2020-03-06
    • 1970-01-01
    • 2021-06-02
    相关资源
    最近更新 更多