# @decocms/compat-v7 中文文档

规范地址：https://npmcn.com/package/%40decocms/compat-v7/

版本：8\.18\.0
npm 元数据更新时间：2026-11-11T12:50:05.061Z
中文译文更新时间：2026-11-12T04:26:58.865Z
软件包许可：未声明

本文由上游 README 翻译，可能存在偏差，请结合原文核对 API、命令与配置。版权与许可归原作者所有。

原始 npm 页面：https://www.npmjs.com/package/%40decocms/compat-v7
原文对照：https://npmcn.com/package/%40decocms/compat-v7/?lang=original
项目主页：https://github.com/decocms/blocks#readme
源码仓库：https://github.com/decocms/blocks

## 关键信息（来自 npm 元数据）

- 包体积（解压后）：525 kB，182 个文件
- 模块格式：ES Module
- TypeScript 类型：包内自带
- 运行依赖：0 个
- peer 依赖：next ^16\.0\.0，react ^19\.0\.0，@decocms/blocks ^8\.4\.0，@decocms/nextjs ^8\.4\.0，@decocms/tanstack ^8\.4\.0，@tanstack/react-start \>=1\.166\.0
- 首次发布：2026-10-15T15:14:15.399Z
- 最新版本发布：2026-11-11T12:50:04.633Z
- 近 30 天下载量：2963（2026-10-12 至 2026-11-10，npm 官方下载统计）
- 已发布版本数：21（近 12 个月 21 个）

## 中文简介

v7 纯助推器( 类型, 设备检测, 内线脚本, clx, 匹配器, 分区加载器跑取器, apps- commerce's 类型和帮助器) 在 @ decocms/ blocks 8 上, V7 输出而无 v7 运行时间; v7 设备上下文和粘着 A/ B cookie 用于 @ decocms/ tast

## 安装

```sh
npm install @decocms/compat-v7
```

也可以使用：`pnpm add @decocms/compat-v7`、`yarn add @decocms/compat-v7`、`bun add @decocms/compat-v7`

## README

# @ decocms/compat-v7 (英语)

v7 的纯帮助站点移出 `@decocms/blocks` 7点到8点 每个都给出了v7的输出,字节表示字节,所以一个迁移的站点从这里导入,而不是保存自己的副本. 测试将每个帮助者标注在v7自己的代码上(最新7.x).

这不是一个v7运行时间。 没有 `ctx`,没有引用,没有请求范围,也没有缓存的加载器:v8没有它们,这个包没有带回它们. 它没有读取环境变量.

端点 : `@decocms/blocks` (同一个版本). 框架子路径还使用网站绑定: `/tanstack` 带 `@decocms/tanstack` 联合国 `@tanstack/react-start` 财务报告和审定财务报表 `react`, (中文(简体) ), `/nextjs` 带 `@decocms/nextjs` 联合国 `next` 财务报告和审定财务报表 `react`) (中文(简体) ). 这些是可选的同伴;一个网站只安装自己的.

## 类型

```ts
import type { ImageWidget, RichText, SectionProps } from "@decocms/compat-v7/types";

export interface Props {
  image: ImageWidget;
  body: RichText;
}

export const loader = async (props: Props, req: Request) => ({ ...props, url: req.url });

export default function Banner(props: SectionProps<typeof loader>) {
  // ...
}
```

-   `SectionProps<typeof loader>` 是装载器的返回值,等待。 v7 还被打开a `Promise`;对于同步加载器,v7给出了加载器自己的类型,在这里给出了值.
-   `Resolved<T>`, (中文(简体) ), `LoadingFallbackProps` 财务报告和审定财务报表 `Flag` 这是v7的.
-   部件的别名( N)`ImageWidget`, (中文(简体) ), `VideoWidget`, (中文(简体) ), `HTMLWidget`, (中文(简体) ), `RichText`, (中文(简体) ), `TextArea`, (中文(简体) ), `Color`, (中文(简体) ), `TextWidget`, (中文(简体) ), `ButtonWidget`, (中文(简体) ), `Secret`)为弦. `deco schema` 读取它们的名字,所以一个字段会像在v7上所做的那样获得网站编辑器的部件. `Secret` 是 v7 的被遮盖的文本框 : 一个在内容中保存的平面字符串, 所以将真实的证书保存在您的部署平台的秘密中, 由网站的代码读取并作为参数通过 . `@decocms/compat-v7/types/widgets` 只有一个别名.

7号 `AppContext` 财务报告和审定财务报表 `FnContext` 不在这里,他们描述 `ctx` 参数,v8不会通过.

## 设备检测

```ts
import { detectDevice, isMobileUA } from "@decocms/compat-v7/device";

const device = detectDevice(request.headers.get("user-agent") ?? ""); // "mobile" | "tablet" | "desktop"
```

这些是v7的用户代理模式,在v7的顺序(tablet first)中检查. `isMobileUA` 电话和平板电脑都是真的.

## 内置脚本

```tsx
import { inlineScript, useScript } from "@decocms/compat-v7/script";

<script {...inlineScript(`document.body.dataset.ready = "true"`)} />
<script dangerouslySetInnerHTML={{ __html: useScript(onLoad, "banner-1") }} />
```

`useScript`, (中文(简体) ), `useScriptAsDataURI` 财务报告和审定财务报表 `inlineScript` 给 v7 输出。 v7 在开发中警告 `fn.toString()`,因为服务器和客户端构建可以以不同的方式序列化一个函数并打破水分. 警告不见了,因为它读到 `NODE_ENV`,但建议仍然有效: `inlineScript` 带一弦.

## 链接

```ts
import { clx } from "@decocms/compat-v7/clx";

clx("btn", isActive && "btn-active", undefined); // "btn btn-active"
```

它会降低发作值,加入其余部分,并像 v7 那样崩溃白空间运行. 像v7,它不会修剪.

## 匹配者

```ts
import { type DeviceProps, device, type RandomProps, random } from "@decocms/compat-v7/matchers";

export const blocks = {
  "website/matchers/device.ts": (props: DeviceProps) => device(props, matcherContext()),
  "website/matchers/random.ts": (props: RandomProps) => random(props, matcherContext()),
};
```

`device`, (中文(简体) ), `cookie`, (中文(简体) ), `host`, (中文(简体) ), `pathname`, (中文(简体) ), `queryString`, (中文(简体) ), `location`, (中文(简体) ), `multi` 财务报告和审定财务报表 `random` 给v7的结果。 v8 块函数只获得其输入, 因此每个匹配者将请求作为其第二个参数: a `Request`,或 `{ request, url, flags }`时 `url` 当请求是客户端导航服务器功能调用时, 是页面的 URL,以及 `flags` 对 A/B 决定,每个请求一个阵列. `matcherContext()` 然而,该站点符合所要满足的要求;框架的子路径提供了这种要求. `always`, (中文(简体) ), `never` 财务报告和审定财务报表 `date` 是v8内置,所以他们不在这里;v8's `date` 命名已保存块的运动 `campaigns`,并移动每个 v7 日期窗口.

-   `random` 是 v7 的粘度随机( 上 7. x) : `deco_segment` cookie),当流量变化时再次被绘制出. 饼干是按键测试的 **组名, 已保存的匹配者块名**一个v8区块不知道自己的名字 所以这个区块把它带进 `cohort`; 随机规则内置使用 `website/matchers/random.ts`和v7一样 改变流量份额时保持组别:重新命名让每个访客都参加新的测试. v7 – v8 迁移不注册: 它报告每个随机匹配者, 将移动到保存的块中 `experiments` (类型) `split-traffic`)在同名下,所以访客保留他们的团体,装订者拥有 `deco_segment`。不要运行两者在一个网站: 饼干的两位作者 撤销彼此的决定.
-   页面解决后, `segmentSetCookie(request, flags)` 给 `Set-Cookie` 发送,或 `null` 当访客的饼干 已经说了同样的话. `decideRandom` 返回一个决定与饼干。 不要缓存一个回应 设置给其他访客.
-   `multi` 获得规则的结果:v8先解决. 内在 `random` v7在每一个请求中都重新画出来.
-   `environment` 抛出:它读取没有 v8 软件包的流程环境。 登记自己的配对者的名字.
-   `location` 读取 `cf-*` 头,然后工人 `request.cf`,然后是 `__cf_geo_*` 饼干,像v7一样.

## 区装填器

```ts
import { compose, runSectionLoaders, withDevice, withSearchParam } from "@decocms/compat-v7/sections";

const loaders = {
  "site/sections/Product/ProductShelf.tsx": withDevice(),
  "site/sections/Header/Header.tsx": compose(withDevice(), withSearchParam()),
  "site/sections/Category/Banner.tsx": async (props, req) => ({ ...props, url: req.url }),
};

// After the page's sections resolved, once per page, globals included:
const { sections, degraded } = await runSectionLoaders(page.sections, { loaders, request, url: pageUrl });
```

`runSectionLoaders` 运行 v7's `(props, req)` 区域加载器 :

-   每个区段运行它的装载器,然后道具中的区段运行,无论它们在哪里(最晚为7.x). 其v7基线为7.77.12或更早通过的地点 `nested: "direct"`:这些释放只运行直接以道具或列表道具保存的部分.
-   一个装填器得到道具 `__pageUrl` 财务报告和审定财务报表 `__pagePath` 添加(在道具中已经获得数值)和 a `GET` 请求页 : `url` 当请求是客户端导航的服务器功能呼叫时, 否则 `request.url`,用请求的页眉.
-   投出道具的加载器是保存的道具. 该节列于 `degraded` 除非是在 `nonCritical` (v7级) `registerNonCriticalSections`; 将 v7 的布局区段也放在那里, 因为 v7 从未标记它们退化). v7 已发送 `X-Deco-Degraded` 当列表不是空的,所以页面没有被边缘标记.
-   `runSectionLoader` 某一节(推迟部分)也是如此.

v7 的缓存( layout 区段, 可缓存区段) 及其注册不在此: 加载器是一个参数 。 v7的第三个论点, `ctx`不见了 一个读取它的加载器扔出一个错误,说出该使用什么来取而代之,而其部分保留了被保存的道具.

`withDevice`, (中文(简体) ), `withMobile`, (中文(简体) ), `withSearchParam`, (中文(简体) ), `compose` 财务报告和审定财务报表 `withSectionLoader` 是v7的混音器,有v7的输出. `withSectionLoader` 保留 v7 的捕获量:一个会扔回道具的区段模块装载器,而区段没有退化.

v8节为 `{ component, props }`. v7 的解析器将嵌入部分写成 `{ Component, props }`;这里的嵌入区段形状与页面区段相同,并保留它拥有的任何其他密钥.

## 商业类型和帮助者

```ts
import type { Product } from "@decocms/compat-v7/commerce/types";
import { formatPrice } from "@decocms/compat-v7/commerce/sdk/formatPrice";
import { useOffer } from "@decocms/compat-v7/commerce/sdk/useOffer";
import { relative } from "@decocms/compat-v7/commerce/sdk/url";
import { mapProductToAnalyticsItem } from "@decocms/compat-v7/commerce/utils/productToAnalyticsItem";
```

7号 `@decocms/apps-commerce`下页 `/commerce` 使用自己的子路径布局: 替换 `@decocms/apps-commerce/` 与 `@decocms/compat-v7/commerce/` 在导入中,没有其他变化.

-   `/commerce/types` (和 `/commerce`: schema.org 商业类型(`Product`, (中文(简体) ), `Offer`, (中文(简体) ), `AggregateOffer`, (中文(简体) ), `BreadcrumbList`, (中文(简体) ), `ProductListingPage`,分析事件,... ),与车型的再出口. `/commerce/types/cart` 单凭手推车类型和区段预设.
-   `/commerce/sdk/*`数字 : `formatPrice`编号 :`formatPriceRange`, (中文(简体) ), `relative`, (中文(简体) ), `useOffer`编号 :`bestInstallment`, (中文(简体) ), `useVariantPossibilities`和分析绘图器`analytics`) (中文(简体) ).
-   `/commerce/utils/*`数字 : `canonicalFromBreadcrumblist`, (中文(简体) ), `DEFAULT_IMAGE`, (中文(简体) ), `parseRange`编号 :`formatRange`, (中文(简体) ), `mapProductToAnalyticsItem`,以及 `getStateFromZip` (默认导出 `stateByZip`) (中文(简体) ).

每个文件都是v7's,格式化一旁,测试运行v7's文件旁边. 无使用反应( N)`useOffer` 财务报告和审定财务报表 `useVariantPossibilities` 是普通函数,尽管名称不同)。 v7 的应用程序运行时间( e)`app-types`, (中文(简体) ), `manifest-utils`, (中文(简体) ), `registry`, (中文(简体) ), `resolve`) 这里没有: v8 配置有参数的客户端.

## TanStack 开始(`@decocms/tanstack`(中文(简体) )

```ts
// the block map
import { random, type RandomProps } from "@decocms/compat-v7/matchers";
import { matcherContext } from "@decocms/compat-v7/tanstack/server";

"website/matchers/random.ts": (props: RandomProps) => random(props, matcherContext()),

// the page's server function (it gets the page's href)
const page = await openPage(data.href);  // resolves the page, so the matchers run
commitSegmentCookie();                   // deco_segment, as v7's page route set it
return { ...page, device: requestDevice() };

// the page component
import { DeviceProvider } from "@decocms/compat-v7/tanstack";
<DeviceProvider value={page.device}>{sections}</DeviceProvider>

// src/worker-entry.ts: the segment of the site's own page cache
const segment = (request: Request) => ({ device: …, ...cohortSegment(request) });
```

-   `matcherContext(pageUrl?)` 给每个匹配者所服务的请求( TanStack Start ) `getRequest()`,页面的 URL 和一个 `flags` 每个请求的阵列。 在客户端导航上,请求是服务器功能呼叫,因此通过该页面的URL,因为v7匹配正在导航的页面;没有它,该呼叫会丢出.
-   `commitSegmentCookie()` 套装 `deco_segment` 将客人们的饼干合并: `deco_segment=<value>; Max-Age=31536000; Path=/; SameSite=Lax`,v7的字节. 当饼干已经说一样的话时,就没什么了. 在页面解析后在服务器函数中调用它 。 一个网站的页面缓存从不存储设置它的响应,因为v7的工人没有: 保留 `deco_segment` 从饼干中取出它的缓存条和商店(工人进入处方) `@decocms/tanstack`README 存储的响应中,没有设置 cookie 以外的响应 `SAFE_COOKIES`) (中文(简体) ).
-   `cohortSegment(request)` 是 v7 边缘缓存的 A/B 拆分(`{ abf: <token> }` 在一个考验中, `{}` 因此,每个组保留自己的缓存页面,其他人共享一个.
-   `requestDevice()` 为 v7's `detectDevice` 关于请求的用户代理:默认情况下工人-输入食谱的缓存密钥用途。 与页面一起返回,所以浏览器的水合值是相同的. `useDevice()` 读取提供者;没有读取浏览器的用户代理(`"desktop"` 和v7一样.

### A/B与遗产来源分离

7号 `withABTesting` (由 KV 驱动在 TanStack 站点与其取代站点之间的分割) 是 `abTestingRoutes`,为 `createDecoWorker`是因为 `routes`数字 :

```ts
// src/worker-entry.ts
import { abTestingRoutes } from "@decocms/compat-v7/tanstack/worker";

const abTesting = abTestingRoutes({
  worker: () => worker,
  kvBinding: "SITES_KV",
  shouldBypassAB: (_request, url) => isCommercePath(url.pathname),
});

const worker = createDecoWorker({
  // …
  routes: async (request, env, ctx) => (await abTesting(request, env, ctx)) ?? siteRoutes(request),
});
export default worker;
```

-   相同的 KV 条目( E)`{ workerName, fallbackOrigin, abTest: { ratio } }` 在请求的主机名下,同一桶(`?_deco_bucket=` 覆盖,然后是 `_deco_bucket=<bucket>:<ratio %>` 在目前比例下设定了饼干,然后是客户IP的散列,同样的饼干和 `x-deco-bucket` 头,断路器, `shouldBypassAB`, (中文(简体) ), `preHandler` 和倒置代理(主机名在 `Set-Cookie`, (中文(简体) ), `Location` 和2xx文本机构,流出)。 测试运行 v7 的文件旁边.
-   v7包了整个工人。 操作器运行在工人运行的地方 `routes`:在CMS重定向后, `/deco/_liveness` 和缓存清洗。 对于"工人"的桶 它叫工人回来(`worker`)),因此页面得到桶饼干,一个工人出错会回落到遗留来源,如v7中;内调会跳过处理器并去站点的其他路线和边缘缓存,这已经让 `_deco_bucket` 通过缓存页面.
-   留下的遗迹的回音 就像工人一样 `routes` 回应 : `CDN-Cache-Control: no-store` 当它没有设置, 工地的安全头 当它没有设置 `preload` 提示( 它们为新站点命名 ; v7 发送了 无) 。 "工人"桶的一页载着他们一次,从制造它的内部呼叫.

## 下册.js`@decocms/nextjs`(中文(简体) )

```ts
// proxy.ts: forward the visitor's URL (with the draft headers, if any)
import { pageUrlRequestHeaders } from "@decocms/compat-v7/nextjs/proxy";
const headers = pageUrlRequestHeaders(request, draftRequestHeaders(request, decision));
return applyDraft(NextResponse.next({ request: { headers } }), decision);

// the block map
import { matcherContext } from "@decocms/compat-v7/nextjs/server";
"website/matchers/random.ts": async (props: RandomProps) => random(props, await matcherContext()),

// the page (a server component)
import { SegmentCookie } from "@decocms/compat-v7/nextjs/server";
const sections = await resolvePage(...);  // the matchers run here
return <>{sections}<SegmentCookie nonce={nonce} /></>;

// app/layout.tsx
import { DeviceProvider } from "@decocms/compat-v7/nextjs";
<DeviceProvider value={await requestDevice()}>{children}</DeviceProvider>
```

-   一个服务器组件看到请求的页眉,但不看到其URL,代理机可能会重写一个页面所绘制的路径. 代理转发访问者要求的 URL `x-deco-page-url` (取出任何外部副本),以及 `matcherContext()` 匹配; 通过 URL 到 `matcherContext(url)` 而不是当页面知道它.
-   这些决定是按React的要求作出的 `cache`。 。 。 .
-   服务器组件不能设置饼干,代理在页面决定前运行. 这么说吧 `SegmentCookie` 制作一行脚本,设置同样的 cookie v7 的 TanStack 路由发送(`deco_segment=<value>; Max-Age=31536000; Path=/; SameSite=Lax`)),或者当访客的饼干已经说了同样的话就什么都没有了. 在客户端导航 React 使页面本身不运行脚本之后,它不会生成脚本,所以一个效果就设置了相同的饼干. 内容解决后再渲染. 阅读请求的一页是动态的,所以Next永远不要在访客之间分享;让一个CDN在前面也不要缓存. v7's Next.js 捆绑从未写过这个饼干: 在那里,随机再次从每个请求中抽取.

设备上下文是两个框架相同的模块: `DeviceContext`。 。 。 .

包根导出类型,设备,脚本和 Clx 帮助. 选手,选手, `/commerce/*` 而框架的子路径 只在自己的子路径.

## 常见问题

### @decocms/compat-v7 是什么？

v7 纯助推器\( 类型, 设备检测, 内线脚本, clx, 匹配器, 分区加载器跑取器, apps- commerce's 类型和帮助器\) 在 @ decocms/ blocks 8 上, V7 输出而无 v7 运行时间; v7 设备上下文和粘着 A/ B cookie 用于 @ decocms/ tast

### 如何安装 @decocms/compat-v7？

在项目目录运行 npm install @decocms/compat-v7，或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖：@decocms/blocks（^8\.4\.0）。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖，Yarn 需要手动安装。

### @decocms/compat-v7 支持 TypeScript 吗？

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

### @decocms/compat-v7 支持 ESM 还是 CommonJS？

以 ES Module 形式发布，推荐使用 import 引入。在 CommonJS 项目中，Node\.js 20\.19\+ / 22\.12\+ 可以直接 require\(\) 不含顶层 await 的 ES Module，更早的版本需要改用动态 import\(\)。

### @decocms/compat-v7 可以商用吗？

@decocms/compat-v7 使用 未声明 许可。package\.json 没有声明许可证。没有许可证的代码默认保留全部权利，商用前请联系作者或查看仓库中的 LICENSE 文件。以上为概括，不构成法律意见，请以许可原文为准。

### @decocms/compat-v7 的下载量有多少？

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

### @decocms/compat-v7 还在维护吗？

最新版本 8\.18\.0 发布于 2026/11/11（今天）；至今共发布 21 个版本，其中过去 12 个月发布了 21 个；首次发布于 2026/10/15。发布频率只是参考信号：功能稳定的工具可能很少需要更新，建议结合源码仓库的 issue 和提交记录判断。

