@wix/site-service-warmup-data
v1.0.6
Published
A site service for reusing data that was fetched during SSR on the client.
Maintainers
Keywords
Readme
@wix/site-service-warmup-data
A site service for reusing data that was fetched during SSR on the client.
The service is a thin adapter over host-provided warmup-data accessors. It does not own serialization, HTML extraction, or storage; the host provides those through getData and setData.
Install
pnpm add @wix/site-service-warmup-dataUsage
import { WarmupDataDefinition } from '@wix/site-service-warmup-data/definition'
const warmupData = servicesManager.getService(WarmupDataDefinition)
const key = `my-feature:product:${slug ?? 'fallback'}`
const cached = await warmupData.get<ProductContextData>(key)
if (cached !== null) {
return cached
}
const data = await fetchProductContextData(slug)
if (typeof window === 'undefined') {
warmupData.set(key, data)
}
return dataHost Registration
Hosts register the service with accessors that connect it to their warmup-data implementation.
import { createServicesMap } from '@wix/services-manager'
import { WarmupDataDefinition } from '@wix/site-service-warmup-data/definition'
import { WarmupDataService } from '@wix/site-service-warmup-data/implementations'
createServicesMap().addService(WarmupDataDefinition, WarmupDataService, {
getData: async key => warmupDataStore.get(key) ?? null,
setData: (key, value) => warmupDataStore.set(key, value),
})API
| Member | Type | Description |
|---|---|---|
| get | <T = unknown>(key: string) => Promise<T \| null> | Reads warmup data for key. Returns null when no data exists. |
| set | (key: string, data: unknown) => void | Stores warmup data for key through the host implementation. Intended for SSR writes. |
Configuration
IWarmupDataServiceConfig:
type IWarmupDataServiceConfig = {
getData: (key: string) => Promise<unknown | null>
setData: (key: string, data: unknown) => void
}Keying
Consumers must use stable, unique keys. Prefer namespaced keys that include the package or feature name and the resource identity:
const key = `stores-product-page:product-context-data:${slug ?? 'fallback'}`Avoid generic keys such as product or data; warmup data is shared through the host and key collisions can return the wrong payload.
SSR And Client Behavior
The intended flow is:
- During SSR, fetch the data and call
set(key, data). - The host serializes the stored value into warmup data.
- On the client, call
get(key)before fetching. - If
get(key)returnsnull, fall back to the normal fetch path.
Client-side writes are not part of the warmup-data contract. Consumers should call set only during SSR. Host implementations may ignore or reject client writes.
Thunderbolt Integration
Thunderbolt registers this service through feature-warmup-data.
On SSR, Thunderbolt provides a request-local service store. Calls to set(key, data) write into that store. During warmup-data aggregation, the store is serialized under the top-level warmup-data key builderComponentsWarmupData:
{
builderComponentsWarmupData: {
[key]: data,
},
}On the client, Thunderbolt reads the serialized warmup-data JSON from the wix-warmup-data script element after DOM ready. Calls to get(key) wait for that warmup-data promise and then read builderComponentsWarmupData[key]. Missing keys return null.
Thunderbolt does not provide the request-local service store in the browser, so calling set on the client throws:
Setting builder component warmup data is only supported during SSRConsumer code should therefore guard writes with an SSR check, or wrap set so warmup-data failures do not break rendering. Reads should also keep the normal fetch path as a fallback when get(key) returns null.
Async Reads And Performance
get(key) returns a promise because the serialized warmup-data payload may not be available when the component code starts running on the client. In Thunderbolt streaming mode, component JavaScript can run before the full document, including the wix-warmup-data script element, has arrived. In that case, get(key) waits for the host warmup-data promise before it can read builderComponentsWarmupData[key].
Waiting for warmup data is not always faster than fetching again. As the warmup-data payload grows, especially on pages with many components using warmup data, the warmup-data promise may resolve later than a cheap client fetch would. Warmup data should be treated as an optimization that needs measurement, not as a guaranteed performance improvement.
Prefer awaiting get(key) when:
- The original fetch is expensive or slow.
- Duplicating the fetch has meaningful server, quota, or side-effect cost.
- Measurements show the warmup-data promise usually resolves before a client fetch would finish.
Consider bounding the wait or skipping warmup data when:
- The client fetch is usually very fast.
- The page can contain many warmup-data consumers.
- Suspending rendering or hydration while waiting for warmup data is more expensive than refetching.
For latency-sensitive flows, measure how long get(key) takes and consider racing it with a small timeout:
function timeout(ms: number): Promise<null> {
return new Promise(resolve => setTimeout(() => resolve(null), ms))
}
const start = performance.now()
const cached = await Promise.race([warmupData.get<ProductContextData>(key), timeout(50)])
const warmupWaitMs = performance.now() - start
reportWarmupDataTiming({ key, warmupWaitMs, hit: cached !== null })
if (cached !== null) {
return cached
}
return fetchProductContextData(slug)Tune the timeout per use case. A good timeout for one component may be wrong for another.
Optional Rollout
When supporting hosts that may not load this service yet, treat it as an optimization:
import { WarmupDataDefinition } from '@wix/site-service-warmup-data/definition'
function getOptionalWarmupData(servicesManager: ServicesManager) {
try {
return servicesManager.getService(WarmupDataDefinition)
} catch {
return null
}
}If the service is unavailable, continue with the existing fetch path.
