@bloomreach/spa-sdk

中文文档
28.2.0发布于 2026/11/02Apache-2.0TypeScriptESM + CJS近 30 天下载 4.6万

Bloomreach SPA SDK

原始使用文档
文档目录10 节
  1. Features
  2. Get Started
  3. Installation
  4. Usage
  5. Relevance Integration
  6. Rendering HTML content safely
  7. Persist preview data for pages without SDK instance
  8. Important notes
  9. License
  10. Reference

Bloomreach SPA SDK

Bloomreach SPA SDK provides simplified headless integration with Bloomreach Content for JavaScript-based applications. This library interacts with the Page Model API and exposes a simplified and framework-agnostic interface over the page model.

Features

  • Page Model API Client
  • Page Model Javascript implementation
  • URL Generator
  • Integration with Bloomreach Experience Manager Preview

Get Started

Installation

To get the SDK into your project with NPM:

npm install @bloomreach/spa-sdk

And with Yarn:

yarn add @bloomreach/spa-sdk

Usage

The following code snippet requests a related page model and shows the page's title.

import axios from "axios";
import { initialize } from "@bloomreach/spa-sdk";

async function showPage(path) {
  const page = await initialize({
    // The path to request from the Page Model API, should include query
    // parameters if those are present in the url
    path,
    // The location of the Page Model API of the brX channel
    endpoint: "http://localhost:8080/delivery/site/v1/channels/brxsaas/pages",
    // The httpClient used to make requests
    httpClient: axios,
  });

  document.querySelector("#title").innerText = page.getTitle();
}

showPage(`${window.location.pathname}${window.location.search}`);

Alternatively, using the native fetch API (a wrapper is needed since fetch is not directly compatible with the HttpClient signature):

import { initialize } from "@bloomreach/spa-sdk";

const httpClient = async ({ method, url, headers, data }) => {
  const response = await fetch(url, {
    method,
    headers: headers,
    body: data !== undefined ? JSON.stringify(data) : undefined,
  });
  return { data: await response.json() };
};

async function showPage(path) {
  const page = await initialize({
    path,
    endpoint: "http://localhost:8080/delivery/site/v1/channels/brxsaas/pages",
    httpClient,
  });

  document.querySelector("#title").innerText = page.getTitle();
}

showPage(`${window.location.pathname}${window.location.search}`);

Relevance Integration

(not applicable to Content SaaS)

The SDK provides basic Express middleware for seamless integration with the Relevance Module.

import express from "express";
import { relevance } from "@bloomreach/spa-sdk/dist/express";

const app = express();

app.use(relevance);

The middleware can be customized using the withOptions method.

app.use(relevance.withOptions({ name: "_visitor", maxAge: 24 * 60 * 60 }));

Rendering HTML content safely

You should/must sanitize any HTML content returned in the page model for security reasons. Before the removal of the sanitize method, we used the sanitize-html package in the SDK for this purpose. You can now use your preferred sanitization libraries or techniques based on your project requirements. Make sure to preserve the data-type attribute on links in the rich content fields when sanitizing as it lets the SDK determine which links are external and which are internal when using the rewriteLinks method.

For example, in a React example, you may sanitize and render the HTML content which came from the backend like the following example:

import sanitize from 'sanitize-html';
  
function sanitizeRichContent(content: string): string {
  return sanitize(content, {
    allowedAttributes: {
      a: ['href', 'name', 'target', 'title', 'data-type', 'rel'],
      img: ['src', 'srcset', 'alt', 'title', 'width', 'height', 'loading'],
    },
    allowedTags: sanitizeHTML.defaults.allowedTags.concat(['img']),
  });
}
/* ... */

/* Suppose the content.value below contains HTML markups string. */
<div>
   {content && <div dangerouslySetInnerHTML={{ __html: page.rewriteLinks(sanitizeRichContent(content.value)) }} />}
</div>

The same principle may apply in other frameworks. e.g, v-html in Vue.js or [innerHTML] in Angular.

Persist preview data for pages without SDK instance

If you are using the SPA SDK selectively on certain pages, you will need to persist the preview related data when navigating between pages that have and those that don't have a SDK instance. The easiest way to achieve this result is by making use of the cookie storage as illustrated below.

The following snippet of the code shows the possible implementation of a function which builds a Configuration object to pass into the initialize function from the SPA SDK or directly to a BrPage component. It reads preview data from the query string and saves it to the cookies, restoring that data if it not available in a query string. To manage the cookies you could use cookie library or any other library.

Important notes

  • The preview site should be served on a separate domain compared to the live site to avoid saving preview related cookies for the live site.
  • In case, when the first page which is loading in preview doesn't use SPA SDK you should parse query parameters and save preview related data to the cookies by yourself.

This is a generic example and you should adjust it to your specific framework.

import axios from 'axios';
import cookie from 'cookie';
import { Configuration } from '@bloomreach/spa-sdk';

export default function buildConfiguration(): Configuration {
  const PREVIEW_TOKEN_KEY = 'token';
  const PREVIEW_SERVER_ID_KEY = 'server-id';
  // Read a token and server id from the query string
  const searchParams = new URLSearchParams(window.location.search);
  const queryToken = searchParams.get(PREVIEW_TOKEN_KEY);
  const queryServerId = searchParams.get(PREVIEW_SERVER_ID_KEY);

  const cookies = cookie.parse(document.cookie);

  // Prioritize values from the query string because cookies might be outdated.
  const authorizationToken = queryToken ?? cookies[PREVIEW_TOKEN_KEY];
  const serverId = queryServerId ?? cookies[PREVIEW_SERVER_ID_KEY];

  // Save the values from the query string to have ability to restore them when switch back from legacy page to the SPA-SDK rendered page.
  if (queryToken) {
    document.cookie = cookie.serialize(PREVIEW_TOKEN_KEY, queryToken);
  }

  if (queryServerId) {
    document.cookie = cookie.serialize(PREVIEW_SERVER_ID_KEY, queryServerId);
  }

  const configuration = {
    endpoint: 'your-pda-endpoint',
    httpClient: axios,
    path: `${location.pathname}${location.search}`,
    // Provide authorization token and server id if they exist to the SPA-SDK initialization method.
    ...(authorizationToken ? { authorizationToken } : {}),
    ...(serverId ? { serverId } : {}),
  };

  return configuration;
};

Alternatively, using the native fetch API:

import cookie from 'cookie';
import { Configuration, HttpClient } from '@bloomreach/spa-sdk';

const httpClient: HttpClient<any> = async ({ method, url, headers, data }) => {
  const response = await fetch(url, {
    method,
    headers: headers as Record<string, string>,
    body: data !== undefined ? JSON.stringify(data) : undefined,
  });
  return { data: await response.json() };
};

export default function buildConfiguration(): Configuration {
  const PREVIEW_TOKEN_KEY = 'token';
  const PREVIEW_SERVER_ID_KEY = 'server-id';
  const searchParams = new URLSearchParams(window.location.search);
  const queryToken = searchParams.get(PREVIEW_TOKEN_KEY);
  const queryServerId = searchParams.get(PREVIEW_SERVER_ID_KEY);

  const cookies = cookie.parse(document.cookie);

  const authorizationToken = queryToken ?? cookies[PREVIEW_TOKEN_KEY];
  const serverId = queryServerId ?? cookies[PREVIEW_SERVER_ID_KEY];

  if (queryToken) {
    document.cookie = cookie.serialize(PREVIEW_TOKEN_KEY, queryToken);
  }

  if (queryServerId) {
    document.cookie = cookie.serialize(PREVIEW_SERVER_ID_KEY, queryServerId);
  }

  const configuration = {
    endpoint: 'your-pda-endpoint',
    httpClient,
    path: `${location.pathname}${location.search}`,
    ...(authorizationToken ? { authorizationToken } : {}),
    ...(serverId ? { serverId } : {}),
  };

  return configuration;
};

License

Published under Apache 2.0 license.

Reference

Typedoc for the SPA SDK is automatically generated and published to https://bloomreach.github.io/spa-sdk/modules/index.html

版本与发布记录

@bloomreach/spa-sdk 共发布 110 个版本,首次发布于 2019/11/25;过去 12 个月发布了 13 个版本。

版本发布日期距今
28.2.0latest2026/11/026 天前
28.1.02026/08/063 个月前
28.0.1-beta.0beta2026/07/313 个月前
28.0.02026/06/194 个月前
27.3.12026/05/215 个月前
27.3.02026/05/066 个月前

其他发布通道:spasdk-137 → 17.0.2-react18.1,SPASDK-224 → 23.4.3-alpha.1,SPASDK-250 → 26.0.0-alpha.0,beta → 28.0.1-beta.0。

关于 @bloomreach/spa-sdk 的常见问题

@bloomreach/spa-sdk 是什么?

Bloomreach SPA SDK

如何安装 @bloomreach/spa-sdk?

在项目目录运行 npm install @bloomreach/spa-sdk,或使用 pnpm add / yarn add / bun add。

@bloomreach/spa-sdk 支持 TypeScript 吗?

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

@bloomreach/spa-sdk 支持 ESM 还是 CommonJS?

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

@bloomreach/spa-sdk 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=20.19.0。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@bloomreach/spa-sdk 可以商用吗?

@bloomreach/spa-sdk 使用 Apache-2.0 许可。宽松许可:允许商业使用、修改和再分发,并附带明确的专利授权;分发时需保留许可与 NOTICE 文件,修改过的文件要注明改动。以上为概括,不构成法律意见,请以许可原文为准。

@bloomreach/spa-sdk 的下载量有多少?

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

@bloomreach/spa-sdk 还在维护吗?

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