SvelteKit SSR期间如何为每个请求创建全局变量
解决方案:基于Svelte Context实现服务端请求隔离的SEO状态管理
核心思路
利用Svelte的Context API为每个服务端请求创建独立的SEO状态上下文,替代模块级变量(避免跨请求污染),让组件内的setPageTitle、allowIndexing等操作仅作用于当前请求的状态,最终由<SEO/>组件读取并应用。
1. 创建SEO上下文模块
新建src/lib/seo-context.js,封装上下文的初始化与获取逻辑:
import { setContext, getContext } from 'svelte'; // 用Symbol作为上下文key,避免命名冲突 const SEO_CONTEXT_KEY = Symbol('seo-context'); // 初始化当前请求的SEO状态与操作方法 export function initSeoContext() { const state = { title: '', indexingAllowed: true }; const setPageTitle = (newTitle) => { state.title = newTitle; }; const allowIndexing = () => { state.indexingAllowed = true; }; const disallowIndexing = () => { state.indexingAllowed = false; }; // 将状态与方法注入上下文 setContext(SEO_CONTEXT_KEY, { state, setPageTitle, allowIndexing, disallowIndexing }); } // 获取当前请求的SEO上下文 export function getSeoContext() { return getContext(SEO_CONTEXT_KEY); }
2. 在根Layout中初始化上下文
修改src/routes/+layout.svelte,确保每个服务端请求都会初始化独立的SEO上下文:
<script> import { initSeoContext } from '$lib/seo-context'; import SEO from '$lib/SEO.svelte'; // 服务端每个请求渲染时都会执行此初始化,生成独立状态 initSeoContext(); </script> <slot /> <SEO />
3. 实现SEO组件
新建src/lib/SEO.svelte,从上下文读取状态并注入页面头部:
<script> import { getSeoContext } from '$lib/seo-context'; const seo = getSeoContext(); </script> {svelte.head} <title>{seo.state.title || '默认页面标题'}</title> {#if !seo.state.indexingAllowed} <meta name="robots" content="noindex, nofollow" /> {/if} {/svelte.head}
4. 在路由组件中调用SEO方法
在任意路由组件(如src/routes/someroute.svelte)中,直接调用上下文提供的方法:
<script> import { getSeoContext } from '$lib/seo-context'; const seo = getSeoContext(); seo.setPageTitle('我的自定义标题'); seo.disallowIndexing(); </script> <h1>我的页面内容</h1>
为什么这个方案能解决跨请求污染问题
- 模块级变量(原方案)是单例的,服务端加载后会被所有请求共享,导致后续请求复用之前的状态。
- Svelte Context是绑定在组件树上的,服务端每个请求都会重新渲染一套组件树,因此每个请求的Context都是独立的,状态完全隔离。
内容的提问来源于stack exchange,提问作者LAZ
相关产品推荐
相关产品推荐

