SvelteKit 中 localStorage 未定义错误的完整解决方案

碧海醫心

碧海醫心

2026-06-06

803人浏览

原创

SvelteKit 中 localStorage 未定义错误的完整解决方案

sveltekit 默认启用服务端渲染(ssr),而 localstorage 是浏览器专属 api,在服务端(node.js 环境)中不可用,直接调用会导致构建失败。本文详解根本原因、推荐检测方式、安全使用模式及 ssr/csr 分离实践。

sveltekit 默认启用服务端渲染(ssr),而 localstorage 是浏览器专属 api,在服务端(node.js 环境)中不可用,直接调用会导致构建失败。本文详解根本原因、推荐检测方式、安全使用模式及 ssr/csr 分离实践。

在 SvelteKit(基于 Vite)项目中,当你在 .ts 或 .svelte 文件中直接使用 localStorage.getItem() 时,Vite 构建流程会同时生成客户端(browser)和服务端(server)两套代码。而服务端运行于 Node.js 环境,全局对象 window 和其子属性 localStorage 均不存在——这正是报错 ReferenceError: localStorage is not defined 的根本原因。

✅ 正确做法:环境检测 + 条件执行

最稳妥的方式是显式判断当前代码是否运行在浏览器环境,仅在浏览器中执行 localStorage 操作。SvelteKit 提供了两种官方推荐方式:

方式一:使用 $app/environment 中的 browser 标志(推荐 ✅)

import { browser } from '$app/environment';

if (browser) {
  const db_exists_key = 'database-exists';
  const db_exists = localStorage.getItem(db_exists_key);

  if (db_exists !== 'exists') {
    await initUnitsAndDimensions();
    await initCalculator();
    localStorage.setItem(db_exists_key, 'exists');
  }
}

✅ 优势:类型安全、零运行时开销(SvelteKit 在编译期可静态分析并剔除服务端分支)、语义清晰。

方式二:传统 typeof window !== 'undefined' 检测(兼容但非最优)

if (typeof window !== 'undefined') {
  const db_exists_key = 'database-exists';
  const db_exists = localStorage.getItem(db_exists_key);

  if (db_exists !== 'exists') {
    await initUnitsAndDimensions();
    await initCalculator();
    localStorage.setItem(db_exists_key, 'exists');
  }
}

⚠️ 注意:该方式虽有效,但在服务端仍会保留 if 判断逻辑(无法被 Tree-shaking 移除),且缺乏类型提示支持。

会译·对照式翻译
会译·对照式翻译

会译是一款AI智能翻译浏览器插件,支持多语种对照式翻译

下载

⚠️ 关键注意事项

  • 不要在 +server.ts 或 +page.server.ts 中使用 localStorage:这些文件纯服务端执行,browser 为 false,window 一定不存在。

  • 避免在 load 函数顶层同步访问 localStorage:即使加了 browser 判断,若 load 被服务端调用,异步初始化逻辑(如 await initXXX())可能被跳过,导致状态不一致。建议将初始化逻辑移至客户端组件(如 onMount)或 +layout.svelte 中:

    <!-- +layout.svelte -->
    <script lang="ts">
      import { onMount } from 'svelte';
      import { browser } from '$app/environment';
    
      onMount(async () => {
        if (browser) {
          const key = 'database-exists';
          if (localStorage.getItem(key) !== 'exists') {
            await initUnitsAndDimensions();
            await initCalculator();
            localStorage.setItem(key, 'exists');
          }
        }
      });
    </script>
  • 替代方案考虑:若需持久化服务端可读的配置,应改用 cookies(通过 cookies.set())或后端数据库;localStorage 仅适用于纯前端状态缓存。

✅ 总结

场景 推荐方案
初始化逻辑需仅在浏览器执行 使用 if (browser) { ... } + $app/environment
需确保服务端完全不执行相关代码 browser 检测优于 typeof window(编译期优化)
涉及用户首次访问行为(如引导、初始化) 放入 onMount,避免 SSR 与 CSR 状态冲突
需跨请求持久化且服务端需感知 改用 HTTP cookies 或服务端存储

遵循以上原则,即可彻底规避 localStorage is not defined 构建错误,并构建出健壮、可维护的 SvelteKit 应用。

相关文章

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
js获取数组长度的方法
js获取数组长度的方法

在js中,可以利用array对象的length属性来获取数组长度,该属性可设置或返回数组中元素的数目,只需要使用“array.length”语句即可返回表示数组对象的元素个数的数值,也就是长度值。php中文网还提供JavaScript数组的相关下载、相关课程等内容,供大家免费下载使用。

2023.06.20

2362

5

js刷新当前页面
js刷新当前页面

js刷新当前页面的方法:1、reload方法,该方法强迫浏览器刷新当前页面,语法为“location.reload([bForceGet]) ”;2、replace方法,该方法通过指定URL替换当前缓存在历史里(客户端)的项目,因此当使用replace方法之后,不能通过“前进”和“后退”来访问已经被替换的URL,语法为“location.replace(URL) ”。php中文网为大家带来了js刷新当前页面的相关知识、以及相关文章等内容

2023.07.04

717

3

js四舍五入
js四舍五入

js四舍五入的方法:1、tofixed方法,可把 Number 四舍五入为指定小数位数的数字;2、round() 方法,可把一个数字舍入为最接近的整数。php中文网为大家带来了js四舍五入的相关知识、以及相关文章等内容

2023.07.04

2180

6

js删除节点的方法
js删除节点的方法

js删除节点的方法有:1、removeChild()方法,用于从父节点中移除指定的子节点,它需要两个参数,第一个参数是要删除的子节点,第二个参数是父节点;2、parentNode.removeChild()方法,可以直接通过父节点调用来删除子节点;3、remove()方法,可以直接删除节点,而无需指定父节点;4、innerHTML属性,用于删除节点的内容。

2023.09.01

637

4

JavaScript转义字符
JavaScript转义字符

JavaScript中的转义字符是反斜杠和引号,可以在字符串中表示特殊字符或改变字符的含义。本专题为大家提供转义字符相关的文章、下载、课程内容,供大家免费下载体验。

2023.09.04

1166

5

js生成随机数的方法
js生成随机数的方法

js生成随机数的方法有:1、使用random函数生成0-1之间的随机数;2、使用random函数和特定范围来生成随机整数;3、使用random函数和round函数生成0-99之间的随机整数;4、使用random函数和其他函数生成更复杂的随机数;5、使用random函数和其他函数生成范围内的随机小数;6、使用random函数和其他函数生成范围内的随机整数或小数。

2023.09.04

2085

4

如何启用JavaScript
如何启用JavaScript

JavaScript启用方法有内联脚本、内部脚本、外部脚本和异步加载。详细介绍:1、内联脚本是将JavaScript代码直接嵌入到HTML标签中;2、内部脚本是将JavaScript代码放置在HTML文件的`<script>`标签中;3、外部脚本是将JavaScript代码放置在一个独立的文件;4、外部脚本是将JavaScript代码放置在一个独立的文件。

2023.09.12

2366

6

Js中Symbol类详解
Js中Symbol类详解

javascript中的Symbol数据类型是一种基本数据类型,用于表示独一无二的值。Symbol的特点:1、独一无二,每个Symbol值都是唯一的,不会与其他任何值相等;2、不可变性,Symbol值一旦创建,就不能修改或者重新赋值;3、隐藏性,Symbol值不会被隐式转换为其他类型;4、无法枚举,Symbol值作为对象的属性名时,默认是不可枚举的。

2023.09.20

1475

5

java访问控制修饰符介绍
java访问控制修饰符介绍

java访问控制修饰符有四种,分别是public、protected、private、默认访问修饰符。详细介绍:1、public,public是最宽松的访问控制修饰符,被修饰的类、方法和变量可以被任何其他类访问,当一个类、方法或变量被声明为public时,它们可以在任何地方被访问,无论是同一个包中的类还是不同包中的类;2、protected修饰符等等。

2023.09.20

498

7

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
热门推荐
/
最新课程
phpStudy极速入门视频教程
phpStudy极速入门视频教程

共6课时 | 54.4万人学习

独孤九贱(4)_PHP视频教程
独孤九贱(4)_PHP视频教程

共89课时 | 131.8万人学习