Gatsby站点生产部署后sessionStorage无法存储键值对
Gatsby生产环境sessionStorage写入失效问题
现象
本地开发、本地预览生产构建包时弹窗表单的sessionStorage逻辑运行正常,部署到线上后对应存储项为空,本地开发环境存储效果如下:
原有实现直接在gatsby-browser.js中绑定window.load事件操作存储:
function addPopUp() { sessionStorage.setItem('popUpKey', true) sessionStorage.setItem('popUpCount', 0) sessionStorage.setItem('startTime', 50); sessionStorage.setItem('GitexForm', false); } window.addEventListener("load", function() { addPopUp() }) function timer() { var AA = sessionStorage.getItem('startTime') window.setInterval(function () { if (AA > 0) { AA -= 1; sessionStorage.setItem('First', AA); } }, 1000); } window.addEventListener("load", function() { timer() })
问题根因
- 直接在gatsby-browser.js顶层绑定原生
window.load事件,没有使用Gatsby官方提供的客户端生命周期钩子。Gatsby生产构建会对脚本做tree-shaking、压缩重排,hydration阶段原生load事件可能因为执行时机错位,要么注册失败,要么执行时页面上下文未完成初始化,导致sessionStorage写入静默失败。 - 两个load事件的执行顺序在生产环境压缩后不固定,存在timer逻辑先执行、存储初始化逻辑后执行的可能,此时读取
startTime拿到null,后续倒计时逻辑直接中断。 - 未做存储可用性检测,部分生产环境的CSP策略、浏览器隐私防跟踪规则、沙箱隔离环境会直接拦截sessionStorage操作,代码没有捕获异常导致整体逻辑中断。
- sessionStorage仅支持存储字符串类型,直接传入布尔值、数字虽然在部分浏览器下会自动隐式转换,但在严格的生产环境沙箱中可能直接抛出类型错误中断逻辑。
修复代码
替换gatsby-browser.js中原有逻辑,使用Gatsby官方的onInitialClientRender生命周期确保代码在客户端初始化完成后执行,同时补全异常捕获、修正逻辑顺序:
// gatsby-browser.js export const onInitialClientRender = () => { // 检测当前环境是否支持sessionStorage,兼容隐私模式/安全沙箱场景 const checkStorageValid = () => { try { const testVal = '__storage_test__' sessionStorage.setItem(testVal, testVal) sessionStorage.removeItem(testVal) return true } catch (err) { return false } } if (!checkStorageValid()) return // 初始化默认存储值,避免重复覆盖,统一转字符串存储 if (!sessionStorage.getItem('popUpKey')) sessionStorage.setItem('popUpKey', 'true') if (!sessionStorage.getItem('popUpCount')) sessionStorage.setItem('popUpCount', '0') if (!sessionStorage.getItem('startTime')) sessionStorage.setItem('startTime', '50') if (!sessionStorage.getItem('GitexForm')) sessionStorage.setItem('GitexForm', 'false') // 修正倒计时逻辑,避免闭包缓存值导致的异常,倒计时结束自动清除定时器 let countDown = Number(sessionStorage.getItem('startTime')) const timer = setInterval(() => { if (countDown > 0) { countDown -= 1 sessionStorage.setItem('First', String(countDown)) } else { clearInterval(timer) } }, 1000) }
上线排查项
- 检查生产环境的CSP(内容安全策略)配置,不要配置禁止存储访问的规则,确保站点自身脚本有足够的执行权限
- 不要将生产站点放在跨域iframe中嵌入,该场景下部分浏览器会触发智能防跟踪规则,限制第一方存储写入
- 部署后打开浏览器控制台查看是否存在
SecurityError类的存储访问报错,根据报错调整对应安全规则即可
内容的提问来源于stack exchange,提问作者praful
相关产品推荐
相关产品推荐

