Angular 19 SSR NodeAppEngine下TanStack Query缓存水合及单例问题问询
新版Angular Node App Engine下TanStack Query SSR缓存水合实现方案
新版Angular Node App Engine支持TanStack Query的SSR缓存水合需求,只是需要调整QueryClient的共享方式——放弃传统Providers单例模式,改用请求级实例化+手动传递的方案,适配其函数式server.ts架构。以下是具体实现步骤:
1. 封装QueryClient创建逻辑
创建一个独立的工厂文件(如query-client.factory.ts),统一管理QueryClient的初始化配置,确保每个请求生成隔离的实例:
import { QueryClient } from '@tanstack/angular-query-experimental'; export function createQueryClient() { return new QueryClient({ defaultOptions: { queries: { staleTime: 60 * 1000, }, }, }); }
2. Server端生成缓存并传递给应用
在server.ts中手动创建QueryClient实例,预获取数据后注入Angular应用,最后将缓存数据嵌入HTML:
import { bootstrapApplication } from '@angular/platform-browser'; import { AppComponent } from './app/app.component'; import { provideServerRendering } from '@angular/platform-server'; import { createQueryClient } from './app/query-client.factory'; import { provideAngularQuery } from '@tanstack/angular-query-experimental'; export default async function handler(req: Request) { // 为当前请求创建独立的QueryClient const queryClient = createQueryClient(); // 预获取需要缓存的接口数据 await queryClient.prefetchQuery({ queryKey: ['home-page-data'], queryFn: () => fetch(`${process.env.API_URL}/home`).then(res => res.json()), }); // 将QueryClient注入应用 const app = await bootstrapApplication(AppComponent, { providers: [ provideServerRendering(), provideAngularQuery(() => queryClient), ], }); // 提取缓存并插入HTML const cacheData = JSON.stringify(queryClient.getQueryCache().getAll()); const renderedHtml = await app.renderToString(); const hydratedHtml = renderedHtml.replace( '</body>', `<script>window.__QUERY_CACHE__ = ${cacheData};</script></body>` ); await app.destroy(); return new Response(hydratedHtml, { headers: { 'Content-Type': 'text/html' } }); }
3. Client端恢复缓存
在main.ts中读取HTML中的缓存数据,初始化客户端QueryClient并恢复缓存:
import { bootstrapApplication } from '@angular/platform-browser'; import { AppComponent } from './app/app.component'; import { provideAngularQuery } from '@tanstack/angular-query-experimental'; import { QueryClient } from '@tanstack/angular-query-experimental'; // 读取server端注入的缓存 const preloadedCache = (window as any).__QUERY_CACHE__ || {}; // 初始化客户端QueryClient并恢复缓存 const queryClient = new QueryClient({ defaultOptions: { queries: { staleTime: 60 * 1000, }, }, }); queryClient.getQueryCache().restore(preloadedCache); // 启动客户端应用 bootstrapApplication(AppComponent, { providers: [provideAngularQuery(() => queryClient)], }); // 清理全局缓存变量 delete (window as any).__QUERY_CACHE__;
关键注意事项
- 每个请求必须创建独立的QueryClient实例,避免SSR请求间的缓存污染;
- 无需依赖全局Providers,通过手动注入的方式实现server端与应用内的QueryClient共享;
- server端渲染完成后必须销毁应用实例,防止内存泄漏。
内容的提问来源于stack exchange,提问作者radekdob
相关产品推荐
相关产品推荐

