@contentful/experiences-client

中文文档
0.10.15发布于 2026/11/07MITTypeScriptESM + CJS近 30 天下载 5852

Delivery client + fetchExperience for Contentful Experiences

原始使用文档
文档目录9 节
  1. What's in here
  2. fetchExperience(experienceOptions, clientOptions, resolveOp…
  3. createClient(options)
  4. fetchDestinationSitemap(destinationOptions, clientOptions, …
  5. NotFoundError
  6. ContentfulViewDeliveryClient
  7. Why a separate package?
  8. Package conventions
  9. License

@contentful/experiences-client

Internal package. Published to npm so framework adapters can resolve it at install time, but you're not meant to import it directly. It comes in transitively via the framework adapter (@contentful/experiences-react, @contentful/experiences-svelte, etc.).

Isolates @contentful/experience-delivery — the generated Experience Delivery client — and owns the free fetch functions, payload conversion, delivery errors, and XDA-derived request types. The shared runtime and complete EventBuilder live in @contentful/experiences-runtime, which depends on this package. Client does not build events or depend on Runtime. The existing free functions remain supported for adapter and application integration.


What's in here

fetchExperience(experienceOptions, clientOptions, resolveOptions)

The primary fetch + resolve entry point. Fetches an Experience payload and resolves it into a PortableRenderPlan in one call. There are three ways to say which Experience:

  • By destination path (recommended for apps): { spaceId, destinationId, path }. The URL path is the Destination path.
  • By destination node id: { spaceId, destinationId, nodeId }.
  • By Experience id: { spaceId, environmentId, experienceId, … }. Use it when you already hold an id, and for preview.

The destination forms are space-scoped (no environmentId, locale, parameters or extensions) and accept personalization; with it set, the request is sent as a POST instead of the cacheable GET. They return PortableRenderPlan | DestinationRedirectResult: a redirect node resolves to { redirect: { path } }, which you follow instead of rendering.

const result = await fetchExperience(
  { spaceId, destinationId, path: '/demo/landing' },
  { accessToken: process.env.CDA_TOKEN! },
  { config: experienceConfig }
);
if ('redirect' in result) return redirect(result.redirect.path);
// result is a PortableRenderPlan

preview: true with a destination throws DestinationPreviewNotSupportedError (a bridge; use the by-id form for preview). It does not fire on the { client } branch.

By-ID options accept a first-class personalization object containing a profile id and events. Additional Experience Delivery options remain under extensions; use extensions: { sourceMap: {} } to request a content source map. Client merges both into the XDA request body and uses the POST operation whenever either capability is present.

By-ID parameters accepts strings, numbers, and one-level Records of strings/numbers: { featuredPosts: { limit: 6, order: '-fields.title' } }. IDs are declared in Experience.parameters and referenced by $parameters/<id>. Delivery validates names, requiredness, fallbacks and values. Collection order is one signed fields.<apiName> or sys.<id> path, never OrderTerm[].

GET uses parameter.<id> and parameter.<id>.<field> in the generated client's queryParams, separate from locale. Empty Records or defined extensions select POST, with structured, unprefixed parameters in the body. dev.10 supports that body through serializer passthrough, although its generated type omits the key; the SDK uses a local typed request extension. Authentication and rename headers remain owned by the generated client. Refetch with changed values and replace the renderer's plan; see the runtime parameters example.

Three positional args group by concern:

ArgTypePurpose
experienceOptions{ spaceId, destinationId, path | nodeId, personalization? } or { spaceId, environmentId, experienceId, locale?, parameters?, personalization?, extensions? }Which Experience to fetch: by destination or by id.
clientOptions{ accessToken, previewToken?, preview?, host? } or { client }How to fetch — inline credentials (with optional preview toggle) or a pre-made client.
resolveOptions{ config, metadata?, debug? }How to resolve — component registry, per-render metadata, and a debug switch.
import { fetchExperience } from '@contentful/experiences-react'; // or experiences-svelte

// Inline credentials — client created internally
const plan = await fetchExperience(
  { spaceId: '...', environmentId: 'master', experienceId: slug, locale: 'en-US' },
  {
    accessToken: process.env.CDA_TOKEN!,
    previewToken: process.env.PREVIEW_TOKEN!, // optional — only required when preview: true
    preview: false, // flip to true for preview mode; picks previewToken + preview host
  },
  {
    config: experienceConfig,
    metadata: { slug }, // flows into resolveData hooks as ctx.experience.metadata
    debug: false, // logs + visible missing-component box when true
  }
);

// Pre-created client — useful when you manage the client lifecycle yourself
import { createClient } from '@contentful/experiences-react';
const client = createClient({ accessToken: process.env.CDA_TOKEN! });
const plan = await fetchExperience(
  { spaceId, environmentId, experienceId },
  { client },
  { config: experienceConfig }
);

Returns PortableRenderPlan. An empty-nodes payload (draft / unpublished / empty locale) resolves to a valid plan with nodes: [] — it is not a 404. For the missing-experience case, catch NotFoundError (re-exported below).

Successful responses can carry upstream field-resolution errors alongside useful content. Core projects recognized errors into optional plan.deliveryDiagnostics records with string fieldPath and message, preserving order and omitting originalError and unknown fields. Client retains the payload errors through by-ID GET/POST and destination conversion; generated-schema compatibility remains Client-owned, with a single normalization point in Core.

Destination errors may have broader shapes, so this projection does not promise complete coverage. An absent field does not prove personalization success or the absence of other upstream errors. Existing diagnostics: Error[], exceptions, 404 handling, and profile behavior are unchanged. See the delivery diagnostic guidance for safe presentation and disclosure.

Preview mode

Configure both tokens up front and flip preview: true per call to hit the preview API.

const experience = await fetchExperience(
  { spaceId, environmentId, experienceId },
  {
    accessToken: process.env.CDA_TOKEN!,
    previewToken: process.env.PREVIEW_TOKEN!,
    preview: previewMode, // boolean — flip per request
  },
  { config: experienceConfig }
);
  • preview: false (or unset) → uses accessToken against the delivery host.
  • preview: true → uses previewToken against the preview host. Throws fetchExperience() called with preview: true but no previewToken was provided if previewToken is missing.
  • host is only for custom base URLs (staging, proxy, per-region). When set, it wins over the preview-derived host — so { previewToken, preview: true, host: 'https://preview-staging…' } uses the preview token against your custom URL.
  • With the { client } option, preview is ignored (bring your own client, bring your own token/host choice).

createClient(options)

Functional constructor over ContentfulViewDeliveryClient matching the SDK's option shape. Maps accessToken → token and host → baseUrl; passes everything else through unchanged. Prefer over new ContentfulViewDeliveryClient({...}) so field names stay consistent with fetchExperience's inline-credentials path.

createClient is a one-time setup primitive — it builds a single client bound to a single token and does not participate in the per-request preview toggle. If you need runtime-dynamic swaps between delivery and preview, use fetchExperience's inline-credentials path ({ accessToken, previewToken, preview }) instead of pre-building a client via createClient and passing { client }.

import { createClient, PREVIEW_HOST } from '@contentful/experiences-react';

// Delivery (default)
const client = createClient({ accessToken: process.env.CDA_TOKEN! });

// Preview — use PREVIEW_HOST + a CPA token
const previewClient = createClient({
  accessToken: process.env.PREVIEW_TOKEN!,
  host: PREVIEW_HOST,
});

// Custom base URL (staging, proxy, per-region)
const customClient = createClient({
  accessToken: process.env.CDA_TOKEN!,
  host: 'https://preview-staging.example.com',
  // headers, timeoutInSeconds, maxRetries, fetch, logging pass through
});

DELIVERY_HOST / PREVIEW_HOST / PREVIEW_WEBSOCKET_HOST

Named constants for the canonical delivery, preview, and Preview Session WebSocket URLs. Use them so you don't have to hardcode the URL strings in your app.

import { DELIVERY_HOST, PREVIEW_HOST, PREVIEW_WEBSOCKET_HOST } from '@contentful/experiences-react';

DELIVERY_HOST; // 'https://xdn.contentful.com'
PREVIEW_HOST; // 'https://preview.xdn.contentful.com'
PREVIEW_WEBSOCKET_HOST; // 'wss://preview.xdn.contentful.com'

createClient is the fixed-mode path — one client, one token, one host. If you need to flip between delivery and preview per request (e.g. an isPreview URL param), use fetchExperience's inline-credentials form with preview: boolean instead of pre-building a client here. See "Preview mode" above.

fetchDestinationSitemap(destinationOptions, clientOptions, paginationOptions?)

Lists every routable path in a published Destination, for static generation, sitemap.xml, or any other bulk walk. It does not hydrate Experiences; feed each path to fetchExperience.

import { fetchDestinationSitemap } from '@contentful/experiences-react';

const paths: string[] = [];
let pageNext: string | undefined;
do {
  const sitemap = await fetchDestinationSitemap(
    { spaceId, destinationId },
    { accessToken: process.env.CDA_TOKEN! },
    { pageNext } // limit defaults to 100, max 1000
  );
  paths.push(...sitemap.items.map((item) => item.path));
  pageNext = sitemap.pages.next;
} while (pageNext);

Each item is { path, experienceId, type }. Cursors (pages.next, pages.prev) are opaque; don't combine pageNext and pagePrev. A missing Destination throws NotFoundError. It is a free function only; the Node and Web runtimes have no sitemap method.

NotFoundError

Re-exported from @contentful/experience-delivery as a value + type. Thrown by the underlying delivery client on 404 responses. Route it to your framework's 404 idiom:

import { fetchExperience, NotFoundError } from '@contentful/experiences-react';

try {
  const experience = await fetchExperience(/* … */);
  // …
} catch (err) {
  if (err instanceof NotFoundError) notFound(); // Next.js
  throw err;
}

The full delivery-client error namespace is also re-exported as ContentfulViewDelivery (UnauthorizedError, ForbiddenError, ConflictError, UnprocessableEntityError, InternalServerError, ContentfulViewDeliveryError, ContentfulViewDeliveryTimeoutError).

ContentfulViewDeliveryClient

Re-exported directly from @contentful/experience-delivery. Exposed for advanced use cases where you want full control over the client (custom base URL, request options, reuse across calls). Most consumers should prefer createClient (above).

import { ContentfulViewDeliveryClient } from '@contentful/experiences-react';

const client = new ContentfulViewDeliveryClient({
  token: process.env.CDA_TOKEN!,
  baseUrl: 'https://xdn.contentful.com', // default delivery endpoint
});

Why a separate package?

@contentful/experiences-sdk-core is intentionally zero-dep and runtime-neutral — it must stay importable without pulling in any network or platform code. The experience delivery client is large (~3,000 generated files) and only needed when doing server-side fetching. Isolating it here means:

  • Core stays lean and usable in any environment (edge, SSR, test fixtures).
  • Future adapters that render from local fixtures or a custom fetch path don't pay the delivery client's weight.
  • The delivery client version can be bumped in one place.

Package conventions

  • Do not import @contentful/experience-delivery from anywhere except this package.
  • Re-export only what framework adapters need to surface to their users.
  • Keep fetchExperience thin — fetch + cast + resolve. Business logic belongs in packages/core.
  • Name mappings between SDK options and delivery-client options live in create-delivery-client.ts — one place to change.

License

MIT. See the repository LICENSE and NOTICE for full attribution.

版本与发布记录

@contentful/experiences-client 共发布 62 个版本,首次发布于 2026/07/21;过去 12 个月发布了 62 个版本。

版本发布日期距今
0.10.15latest2026/11/074 天前
0.10.142026/11/055 天前
0.10.132026/11/055 天前
0.10.122026/11/056 天前
0.10.112026/11/046 天前
0.10.102026/10/3111 天前

关于 @contentful/experiences-client 的常见问题

@contentful/experiences-client 是什么?

Delivery client + fetchExperience for Contentful Experiences

如何安装 @contentful/experiences-client?

在项目目录运行 npm install @contentful/experiences-client,或使用 pnpm add / yarn add / bun add。

@contentful/experiences-client 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@contentful/experiences-client 支持 ESM 还是 CommonJS?

同时提供 ES Module 与 CommonJS 入口,import 和 require() 都可以使用,打包工具会自动选择合适的版本。

@contentful/experiences-client 可以商用吗?

@contentful/experiences-client 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@contentful/experiences-client 的下载量有多少?

根据 npm 官方下载统计,@contentful/experiences-client 在 2026/10/11 – 2026/11/09 这 30 天内被下载 5,852 次,日均约 195 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@contentful/experiences-client 还在维护吗?

最新版本 0.10.15 发布于 2026/11/07(4 天前);至今共发布 62 个版本,其中过去 12 个月发布了 62 个;首次发布于 2026/07/21。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。