修复Sveltekit应用程序中的无限重定向循环
#javascript #编程 #svelte #sveltekit

我最近在我们的Sveltekit应用程序中调试了一个奇怪的问题 - 用户将被困在一个状态下,页面不断地循环中不断刷新。关闭浏览器和/或清除缓存是解决问题的唯一方法。

一段时间后,我终于设法重现了这个问题。事实证明,这是在您在用户在浏览器中打开旧版本时部署新版本后发生的。

当您部署新版本时,所有资产路径(CSS&JavaScript)将因VITE和汇总工作的方式而改变。捆绑资产的文件名称其名称中具有唯一的哈希,代表文件的内容。

如果用户具有旧版本打开,并且试图导航到新页面,则将触发客户端导航,该导航通常需要从服务器加载新的JavaScript资产。但是,由于您部署了一个新版本,因此旧资产不再存在,并且会返回404错误。 Sveltekit中有一个内置功能,它将检测到资产未能加载并执行页面上的硬刷新

这是我们的问题开始的地方。 如果页面本身的HTML响应被缓存在浏览器中,则仍将指代不再存在的现在古老的资产路径。这触发了页面的刷新,并且循环已经启动。

当我们不将任何缓存标头从应用程序传递到浏览器时,就会发生这种情况。浏览器将选择一个任意时间来缓存我们的内容。 这通常不是所需的行为

解决方案

我们需要设置一个明确的no-cache标头,以供您对来自您应用的HTML文件的响应。您可以使用此代码对hooks.server.ts中的大多数适配器执行此操作:

import type { Handle } from '@sveltejs/kit';

export const handle = (async ({ event, resolve }) => {
  const response = await resolve(event);
  response.headers.set('cache-control', 'no-cache');
  return response;
}) satisfies Handle;

除此之外,我们还需要确保src/routes文件中的+layout.ts包含以下行:

export const prerender = false;

这是因为Sveltekit默认情况下会尝试预先介绍路线,如果它们是预先介绍的,那么它们将被视为完全静态,甚至不会贯穿我们的hooks.server.ts逻辑!这是documented,但在adapter-node的背景下有些奇怪。