SSR、身份与缓存组合
公共内容和请求级身份分别处理,避免把个人会话放入共享客户端。
公共内容客户端
使用绝对地址和明确超时创建公开读取器;不附加个人Cookie。React cache可合并同次渲染,不作为跨请求内容缓存。
TypeScript
import type { Shell } from '@mosaic-base/shell';
import type { ArticleSDK, SiteSDK, I18nSDK } from '@mosaic-base/client-sdk';
import type { AuthClient, ServerAuthClient } from '@mosaic-base/auth-sdk';
// Declare once in your application's type contract, never import SDK implementations.
declare module '@mosaic-base/shell/contracts' {
interface SdkRegistry {
'site.config': Pick<SiteSDK, 'getConfig'>;
'content.articles': Pick<ArticleSDK, 'list' | 'getBySlug' | 'getPreview' | 'search'>;
'i18n.messages': Pick<I18nSDK, 'load' | 't' | 'clearCache' | 'refresh'>;
'auth.client': AuthClient | ServerAuthClient;
}
}
import type { Bootstrap } from '@mosaic-base/shell';
import { startShell } from '@mosaic-base/shell/bootstrap';
import { createNodeModuleLoader } from '@mosaic-base/shell/node';
const loader = createNodeModuleLoader(); // modules may be shared, user SDK instances may not
export function createPublicReader(bootstrap: Bootstrap, apiBaseUrl: string) {
return startShell({ bootstrap, loader, host: { apiBaseUrl,
capabilityOptions: { 'i18n.messages': { cacheTtlMs: 0 } } } });
}
// Read protected Node bootstrap with server-sdk and explicit grant/owner.
// Create/dispose one Shell per SSR operation/request; public HTTP omits Cookie.
// Pass that startup configuration's browser projection to hydration.请求级认证客户端
每次传入本次请求Headers创建认证客户端。宿主在可写响应中完成刷新,再让服务端消费更新后的Cookie。不要在模块全局保存某个用户身份。
TypeScript
import type { Shell } from '@mosaic-base/shell';
import type { ArticleSDK, SiteSDK, I18nSDK } from '@mosaic-base/client-sdk';
import type { AuthClient, ServerAuthClient } from '@mosaic-base/auth-sdk';
// Declare once in your application's type contract, never import SDK implementations.
declare module '@mosaic-base/shell/contracts' {
interface SdkRegistry {
'site.config': Pick<SiteSDK, 'getConfig'>;
'content.articles': Pick<ArticleSDK, 'list' | 'getBySlug' | 'getPreview' | 'search'>;
'i18n.messages': Pick<I18nSDK, 'load' | 't' | 'clearCache' | 'refresh'>;
'auth.client': AuthClient | ServerAuthClient;
}
}
export async function readRequestUser(shell: Shell) {
const auth = await shell.getSdk('auth.client');
return auth.getUser();
}
// Create the request Shell with only auth.client's Cookie policy and realmKey option.
// Dispose in the request owner. Node SDK is read-only; renewal is a writable boundary.实际词条场景
词条页面分别展示SSR与CSR读取。切换语言时只接受当前选择的响应;清缓存后旧请求不能污染新缓存。失败时保留内置文案与重试入口。