如何基于国家缓存SvelteKit站点的不同页面版本?
针对你的场景——仅基于country Cookie值区分缓存版本,而非所有Cookie,以下是几种可行的实现方案:
方案1:服务器端提取country值生成自定义缓存键
在SvelteKit的hooks.server.js中,手动解析Cookie获取country值,以此构建专属缓存键,实现精准的版本区分。这种方式完全由你控制缓存逻辑,不受其他Cookie影响。
示例代码:
// hooks.server.js import { parse } from 'cookie'; // 小流量站点可用内存Map,大流量建议替换为Redis等分布式缓存 const pageCache = new Map(); export async function handle({ event, resolve }) { // 解析Cookie获取country,设置默认值(如US) const cookies = parse(event.request.headers.get('cookie') || ''); const country = cookies.country || 'US'; // 构建缓存键:路径+country值 const cacheKey = `${event.url.pathname}-${country}`; // 检查缓存是否存在 if (pageCache.has(cacheKey)) { return new Response(pageCache.get(cacheKey), { headers: { 'Cache-Control': 'public, max-age=3600' } }); } // 无缓存则渲染页面 const response = await resolve(event); const responseBody = await response.text(); // 存入缓存 pageCache.set(cacheKey, responseBody); // 设置缓存控制头 response.headers.set('Cache-Control', 'public, max-age=3600'); return response; }
方案2:CDN层过滤Cookie并使用自定义Vary头
如果你使用Cloudflare、Netlify等CDN服务,可以在CDN层面提取country Cookie,转换为自定义请求头(如X-Country),然后将Vary头设置为该自定义头。这样CDN只会基于X-Country的值缓存不同版本,忽略其他Cookie变化。
以Cloudflare Workers为例,示例代码:
addEventListener('fetch', event => { event.respondWith(handleRequest(event.request)); }); async function handleRequest(request) { let country = 'US'; const cookies = request.headers.get('cookie'); // 提取country Cookie值 if (cookies) { const cookieEntries = cookies.split(';').map(item => item.trim().split('=')); const countryCookie = cookieEntries.find(([key]) => key === 'country'); if (countryCookie) country = countryCookie[1]; } // 修改请求,添加自定义X-Country头 const modifiedRequest = new Request(request, { headers: new Headers(request.headers) }); modifiedRequest.headers.set('X-Country', country); // 转发请求并设置Vary头 const response = await fetch(modifiedRequest); const modifiedResponse = new Response(response.body, response); modifiedResponse.headers.set('Vary', 'X-Country'); return modifiedResponse; }
在SvelteKit的load函数或钩子中,可通过event.request.headers.get('X-Country')获取地区值,再调用Shopify API返回对应内容。
方案3:将country嵌入URL路径/查询参数
把country值作为URL的一部分(如/us/products或/products?country=us),利用URL天然的唯一性作为缓存键。这种方式无需处理Cookie相关的缓存逻辑,缓存系统会自动区分不同版本。
示例实现(动态路由):
<!-- src/routes/[country]/+page.server.js --> export async function load({ params }) { const country = params.country; // 调用Shopify Storefront API获取对应国家的商品价格 const products = await fetch(`https://your-shopify-store.myshopify.com/api/2024-07/graphql.json`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-Shopify-Storefront-Access-Token': 'your-token' }, body: JSON.stringify({ query: ` query getProducts($country: CountryCode) { products(first: 10) { edges { node { title priceRange { minVariantPrice { amount currencyCode } } } } } } `, variables: { country: country.toUpperCase() } }) }).then(res => res.json()); return { products, country }; }
注:需要处理默认跳转逻辑——当用户访问无country的URL时,根据Cookie或IP重定向到对应地区的URL。
内容的提问来源于stack exchange,提问作者chromata31
相关产品推荐
相关产品推荐

