Middleware e matchers
decoState, observability, healthMetrics, hydrationContext, validateSection, mais matchers built-in e PostHog.
Middleware e matchers são as duas formas como o framework injeta comportamento sem precisar de código de site. Esta página documenta o que vem na caixa.
Middleware
@decocms/start/middleware exporta funções que rodam contra o request/response.
decoState
Provê o MeshContext -style state que loaders e sections leem via RequestContext.current . Conecta automaticamente — não chame manualmente.
observability
Liga tracing OpenTelemetry e Server-Timing. Habilitado por default.
import { observability } from "@decocms/start/middleware";
A maioria dos sites não toca; só envolva manualmente para customização avançada (custom span attributes etc.).
healthMetrics
Expõe /_health (200 OK) e métricas básicas. Habilitado por default.
hydrationContext
Coordena hidratação entre TanStack Router e React 19 Suspense. Crucial para evitar mismatches de hidratação em sections deferred. Embutido em DecoPageRenderer .
validateSection
Garante que toda section que entra na renderização passa por error boundary e tem fallbacks. Auto-aplicado por applySectionConventions no setup. Não chame na mão.
Composição
Middlewares se combinam. O framework já compõe na ordem certa em createDecoWorkerEntry ; você raramente compõe manualmente.
Matchers built-in
@decocms/start/matchers/builtins provê matchers prontos para A/B, segmentação e flags:
| Matcher | Casa por |
|---|---|
MatchUserAgent | Device do Cloudflare ou regex de UA |
MatchDate | Intervalo de datas (start/end ISO 8601) |
MatchSite | siteName atual |
MatchEnvironment | env.ENVIRONMENT (e.g. “staging”) |
MatchLocation | Header cf-ipcountry (país/região) |
MatchSession | Atributo de sessão (logado, com carrinho etc.) |
MatchRandom | Bucket aleatório sticky com sessionKey |
MatchFeatureFlag | Flag PostHog (delegada para o matcher PostHog) |
Registre tudo de uma vez:
import { registerBuiltinMatchers } from "@decocms/start/matchers/builtins";
registerBuiltinMatchers({
customMatchers: {
// matchers próprios do site
MatchHasCart: matchHasCart,
},
});
Após o registro, aparecem nos pickers do admin pelo nome.
MatchRandom (A/B sticky)
O primitivo mais usado para A/B:
{
"__resolveType": "$live/matchers/MatchRandom.ts",
"percentage": 50,
"sessionKey": "ab_hero_v2"
}
percentage— 0-100, porcentagem alocada para “true”.sessionKey— identificador único do experimento. O primeiro request da sessão recebe um veredito; requests seguintes na mesma sessão honram o veredito.
A persistência da sessão usa cookies; setado uma vez, expira em 30 dias por default.
Matcher PostHog
@decocms/start/matchers/posthog integra com flags do PostHog:
import { matchPosthog } from "@decocms/start/matchers/posthog";
Setup:
- Crie um block do app PostHog no admin (
__resolveType: "deco-posthog"ou similar) com a config da chave de API. - Registre o matcher:
registerBuiltinMatchers({ ... })o pega viacustomMatchers: { MatchPosthog: matchPosthog }.
O matcher posta no edge endpoint do PostHog em request time, então respeita as definições de flag do PostHog (alvos por usuário, rollouts %).
Sticky sessions
Por padrão, matchPosthog lê o ID distinct do PostHog do cookie. Sem cookie, gera um por request. Para sticky entre sessões, garanta que o cookie do PostHog é setado pelo seu snippet PostHog client-side ou via setPosthogCookie ( @decocms/apps/posthog ).
Por ambiente
Use uma chave de projeto PostHog diferente por ambiente:
// no app PostHog block:
{ apiKey: env.ENVIRONMENT === "production" ? "phc_prod" : "phc_staging" }
Isso evita poluir analytics de produção com tráfego de staging.
Matchers custom
Um matcher é um arquivo no estilo de section em src/matchers/ :
// src/matchers/MatchHasCart.ts
import type { MatcherFn } from "@decocms/start/types";
export interface Props {
inverse?: boolean;
}
const matcher: MatcherFn<Props> = ({ request }, { inverse = false }) => {
const hasCart = request.headers.get("cookie")?.includes("checkout.vtex.com__orderFormId");
return inverse ? !hasCart : Boolean(hasCart);
};
export default matcher;
A interface Props vira JSON Schema para o admin (igual sections).
Registre via customMatchers em registerBuiltinMatchers :
registerBuiltinMatchers({
customMatchers: {
MatchHasCart: matchHasCart,
},
});
Tracing de matchers
Toda chamada de matcher pega um span. Em wrangler tail aparece como:
matcher.MatchUserAgent status=true duration=2ms
matcher.MatchRandom status=false duration=1ms
Inestimável quando um experimento de A/B não está fazendo o que você espera.
Padrões de matcher composto
Multivariate blocks compõem matchers em decisões em árvore:
{
"__resolveType": "$live/matchers/MultivariateBlock.ts",
"variants": [
{
"matcher": {
"__resolveType": "$live/matchers/And.ts",
"matchers": [
{ "__resolveType": "$live/matchers/MatchUserAgent.ts", "device": "mobile" },
{ "__resolveType": "$live/matchers/MatchHasCart.ts" }
]
},
"block": { "__resolveType": "..." }
},
{ "block": { "__resolveType": "..." } }
]
}
$live/matchers/And.ts e $live/matchers/Or.ts vêm na caixa.
Veja também
Found an error or want to improve this page?
Edit this page