Vite 8.3.3 SSR 请求带查询参数后内存猛涨:检查 transformIndexHtml
SSR 开发环境只有访问带查询参数的首页才卡住,内联 style 可能让 Vite 8.3.3 把文件系统根目录加入 watcher。
SSR 开发服务刚启动正常,访问 /?utm_source=x 后却变慢、内存持续上涨,普通 / 和 /about?x=1 没有同样表现。若使用 Vite 8.3.3,模板含内联 <style>,并把完整请求 URL 交给 transformIndexHtml,检查 watcher 是否意外加入了文件系统根目录 /。
这条回归集中在开发 HTML 转换。Linux 下监听根目录会引出大量文件遍历;macOS 使用不同监听机制,现场可能没那么明显。不能因此把所有 SSR 内存增长都归为这个条件。
目录被误当成真实 HTML 文件
SSR 服务器常按下面的形状处理模板:
const html = await vite.transformIndexHtml(req.originalUrl, template);
8.3.3 的文件名计算先去掉查询参数,于是 /?x=1 对应项目根目录;后面判断仍针对带查询的 URL,并把“路径存在”当成“HTML 文件存在”。内联 style 的代理模块继而得到 / 这样的文件标识,进入额外监听。
保留 Vite 实际版本、触发 URL、模板和监听证据。不要为了证明问题直接在业务主机上开启根目录递归监听;在已有诊断日志或受控检查中观察添加了什么路径即可。真实 HTML 文件、普通静态目录与代理模块身份应分开核对。
8.3.4 已改为检查真实文件
Vite 8.3.4 的正式实现要求该路径确实是文件,而不只是存在。项目与框架允许时,采用包含这一修改的正式版本,保存清单与锁文件并重启原开发服务。上层框架内置 Vite 时,确认实际运行的那份版本,不能只在顶层另装一个新包。
暂时无法更新时,可只给 HTML 转换传文档路径:
const htmlPath = req.originalUrl.split('?')[0];
const html = await vite.transformIndexHtml(htmlPath, template);
这是普通请求 URL 形态下的局部示例,放在原 SSR 处理链里;如果框架已有 URL 解析器,应复用其 pathname。原请求和查询参数仍保留给路由、服务端渲染与业务处理,不能把整个 req.url 改掉,导致搜索参数消失。
这项处理改变的是 HTML 文档路径。依赖原始查询参数的自定义 HTML 插件也需要核对,不应对所有中间件输入全局去掉查询。
覆盖原来的三种地址
重启后分别访问 /、/?x=1 与一个带查询的子页面,模板仍保留原内联 style。确认 watcher 不再因该请求加入 /,服务能持续响应,热更新和样式正常。只移除 style 后观察内存下降,没有验证原路径得到修复。
生产构建不走同一开发监听流程,应另按项目原流程检查。回退时恢复依赖、锁文件和临时路径处理的对应组合;内存已经被旧监听占用时,需要停止旧开发进程,不能只刷新浏览器。


