# @decocms/nextjs 中文文档

规范地址：https://npmcn.com/package/%40decocms/nextjs/

版本：8\.18\.0
npm 元数据更新时间：2026-11-11T12:51:31.114Z
中文译文更新时间：2026-11-11T19:27:48.862Z
软件包许可：未声明

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

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

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

- 包体积（解压后）：301 kB，84 个文件
- 模块格式：ESM + CJS
- TypeScript 类型：包内自带
- Node.js 要求：\>=24
- 运行依赖：0 个
- peer 依赖：next ^16\.0\.0，react ^19\.0\.0，@decocms/blocks ^8\.6\.0，@opentelemetry/api ^1\.0\.0
- 首次发布：2026-07-07T19:36:36.331Z
- 最新版本发布：2026-11-11T12:51:30.647Z
- 近 30 天下载量：12559（2026-10-12 至 2026-11-10，npm 官方下载统计）
- 已发布版本数：252（近 12 个月 252 个）

## 中文简介

Deco CMS for any Next.js App Router app: 代理服务器和页面中的预览草稿,预览徽章, Studio Bridge, 有Deco () 和一个下一张/图像加载器

## 安装

```sh
npm install @decocms/nextjs
```

也可以使用：`pnpm add @decocms/nextjs`、`yarn add @decocms/nextjs`、`bun add @decocms/nextjs`

## README

# @ decocms/ nextjs (英语)

Deco CMS 用于任何 [下一个.js](https://nextjs.org/) App路由器应用程序. 它不设定托管假设:没有构建CDN,ISR或平台行为. 这是一组小的帮助者 您的网站呼叫 从自己的代理,布局,页面和 `next.config`。 。 。 .

端点 : `@decocms/blocks` (同一个版本), `next` 16岁, `react` 19;可选 `@opentelemetry/api` (见 [请求参数](https://npmcn.com/package/%40decocms/nextjs/#readme-request-metric)) (中文(简体) ).

| 导入 | 它是为了什么 |
| --- | --- |
| `@decocms/nextjs/proxy` | 请求的内容,一旦决定 `proxy.ts`数字 : `decideDraft`, (中文(简体) ), `draftRequestHeaders`, (中文(简体) ), `rewriteToDraftRoute`, (中文(简体) ), `applyDraft`, (中文(简体) ), `isDraftRoutePath`, (中文(简体) ), `decideVisitor`, (中文(简体) ), `visitorRequestHeaders`, (中文(简体) ), `applyVisitor`, (中文(简体) ), `decideAssignments`, (中文(简体) ), `assignmentsRequestHeaders`,或 `draftProxy` 用于没有自己代理的网站; `assignmentsKey` 用于一个站点的缓存密钥; `rewriteToAssignmentsRoute`, (中文(简体) ), `isAssignmentsRoutePath`, (中文(简体) ), `assignmentsRoutePath` 财务报告和审定财务报表 `assignmentsSegment` 给 Next 自己的缓存。 没有反应和块图. |
| `@decocms/nextjs/server` | 在 Server 组件中, 代理决定的内容 : `bindDraft`, (中文(简体) ), `activeDraftPointer`, (中文(简体) ), `contentClient`· ; `assignedClient` 用于任务路径上的一页. |
| `@decocms/nextjs` | `DraftPreviewIndicator` (页面草稿上的"审查模式"徽章), `StudioBridge` (lets Studio的网站编辑器驱动页面)和 `StudioPage` (在屏幕上显示是哪一页),加上名字草稿和工作室的出处(下). |
| `@decocms/nextjs/config` | `withDeco(nextConfig)`:草案头规则和工作室的dev起源. 常见JS,所以 `next.config.js` 能够 `require()` 这个. |
| `@decocms/nextjs/instrumentation` | `register`,则 `instrumentation.ts` 钩子记录 `http.server.request.duration` 从Next自己的请求跨度,和 `serverRequestSpanProcessor()` 用于拥有自己的OpenTeleometry SDK的站点. |
| `@decocms/nextjs/image-loader` | `createDecoImageLoader(imageUrl)`: 下一个/图像加载器超过一个 `ImageUrl` 从 `@decocms/blocks/image`。 。 。 . |

`createCMS` 读取 `NODE_ENV` 决定 dev 模式,所以 `next dev` 永远不要将主机的发布替换为本地内容; 不需要通过 . `createCMS({ dev })` 当一个网站需要时,它仍然可以覆盖.

## 草稿

```ts
// src/cms.config.ts: the options both CMS handles share (with `site`, hosted releases and
// the preview hosts Studio writes into them)
export const cmsConfig = { content, site: "my-store" };

// src/cms.ts and src/cms.proxy.ts
export const cms = createCMS({ blocks, ...cmsConfig });
export const proxyCms = createCMS({ blocks: {}, ...cmsConfig }); // no block map in the proxy

// src/proxy.ts
export async function proxy(request: NextRequest) {
  if (isDraftRoutePath(request.nextUrl.pathname)) return new NextResponse(null, { status: 404 });
  const draft = await decideDraft(proxyCms, request);
  const visitor = decideVisitor(request, draft);
  const assignments = await decideAssignments(proxyCms, draft, visitor);
  const headers = assignmentsRequestHeaders(
    visitorRequestHeaders(draftRequestHeaders(request, draft), visitor),
    assignments,
  );
  const response =
    rewriteToDraftRoute(request, draft, visitor, assignments) ??
    NextResponse.next({ request: { headers } });
  return applyVisitor(applyDraft(response, draft), visitor);
}

// src/app/%5Fdraft/[[...path]]/page.tsx: the dynamic draft route (a literal `_draft` folder never routes)
export const dynamic = "force-dynamic";
export default async function DraftPage({ params, searchParams }) {
  await bindDraft(cms, { searchParams: await searchParams });
  const client = contentClient(cms);
  // … resolve and render the page as on the published route …
  return <>{page}<DraftPreviewIndicator /></>;
}
```

已出版的页面保留缓存( ISR, 下面): 代理只向草稿路由发送预览请求( 任何) `?__draft=`, (中文(简体) ), `off` 包含,或 cookie 草稿; 永远不指定任务路由),设置 cookie 草稿, 转发已接受的版本 `x-deco-version` (删除从外部发送的任何副本),并准确标明答复 `Cache-Control: max-age=0, no-cache, must-revalidate`, (中文(简体) ), `Vary: Cookie` 财务报告和审定财务报表 `X-Robots-Tag: noindex, nofollow`一份要求检查草稿,以核实最近一次发布(`cms.checkRelease()`)并转发支票的id `x-deco-release-check` (删除外部发送的任何副本): 代理主机检查并阅读草稿, `bindDraft`'主机检查和页面' `contentClient` 全部等待这个检查, 因此一个预览请求会获取 `latest.json` 一次(在另一个过程中的一页,而不是代理进行自己的检查)。 它在转发之前会读到一个链接的草稿: 无法读取的草稿会让发行, 过期的饼干,并告诉上面的页 `x-deco-draft-unavailable`这样 `DraftPreviewIndicator` 显示平静的通知而不是错误页。 阅读内容的布局随其路线而去,所以被缓存的页面读取不请求: 在草稿路由下(`app/%5Fdraft/layout.tsx`它召唤 `bindDraft(cms)` 财务报告和审定财务报表 `contentClient(cms)`,它读取转发头;在任务路线下(`app/%5Fassignments/[assignments]/layout.tsx`它读过 `await assignedClient(cms, (await params).assignments)`。 。 。 . `bindDraft` 读取 `headers()`,而一个读取请求头的缓存页面则在每一份请求上生成,因此从不在根版式或任务路线上调用它.

草稿链接可以携带已公布的发行承诺SHA来代替草稿(Studio's "Preview this version"),任何一种都可以携带一个预览时间(S`__at`测试和运动开启或关闭(`__test`, (中文(简体) ), `__campaign`页:1 `cms.readVersion` 读作客户端的 `date`, (中文(简体) ), `experiments` 财务报告和审定财务报表 `campaigns`. 全部通过同一主机检查,并在路由草稿上制作:现场的访客从不选择一个版本. 预览会以 0 的速度切换测试 .

### 访客、任务和客户

代理决定每个请求一次. `decideVisitor(request, draft)` 阅读访客 `readVisitor` 从 `@decocms/blocks/experiments` (单位:千美元) `deco_segment` 饼干或新访客; `applyVisitor` 它的饼干只是第一次访问 从来没有从预览. `decideAssignments(proxyCms, draft, visitor)` 然后决定每次测试和运动: `cms.client({ visitor, version, date, experiments, campaigns })` 与访客和 Studio 链接的版本, 瞬间和切换测试和运动 `experiments` 财务报告和审定财务报表 `campaigns` 块. `visitorRequestHeaders` 财务报告和审定财务报表 `assignmentsRequestHeaders` 转发到 `x-deco-visitor` 财务报告和审定财务报表 `x-deco-assignments` (单位:千美元)`draftRequestHeaders` 总是从外部取出副本).

在页面上, `bindDraft` 绑定版本和代理转发的内容(在当前发布时,它绑定访问者和任务,只有在发布时保存一个) `experiments` 或者说 `campaigns` 块,且测试为0 %,无论信头上怎么说,均不进行) `contentClient(cms)` 正在建设 `cms.client({ version, experiments, campaigns })` 从他们那里:页面不再决定什么。 页面信任这些标题:在代理后,他们持有它所决定的东西,以及一个没有它就能达到页面的要求(a) `matcher` 或一个没有代理的网站) 被读取相同的方式,随什么 `x-deco-version` 财务报告和审定财务报表 `x-deco-assignments` 它会随身而来 哪些路线通过代理, 和如何保护其他人, 是网站的呼声。 缓存页面不读取请求: CMS 的页面渲染到 [任务路径](https://npmcn.com/package/%40decocms/nextjs/#readme-the-assignments-route),随着测试和运动 代理决定的道路.

绑定的缓存什么也没有。 在 Next 前面缓存页面的站点( CDN 键入请求头) 在请求的任务上按键, 绝不在访客上 : `assignmentsKey(assignments)` 从 `@decocms/nextjs/proxy`,与什么 `decideAssignments` 提供,是版本,测试和运动运行(`""` 当没有的时候。 每个测试的同一侧的访客共享一个条目,一次运动开始或结束都会改变关键. 让Next自己去缓存看看 [任务路径](https://npmcn.com/package/%40decocms/nextjs/#readme-the-assignments-route)。 。 。 .

### 任务路线

代理决定, 页面使这一点。 下一页按其路径缓存( ISR) , 因此代理将其决定放入路径: 它将每个 CMS 页面重写为 `/_assignments/<assignments>/<path>`,该页面则精确地进行分区名称的测试和活动。 然后,每条路径和一组任务都保留一个条目,并提供给每个访问者使用;页面没有读取请求,所以Next可以缓存. CMS的网页为ISR `revalidate = 600` (10分钟):下一个服务一个被存储了10分钟的页面;之后的第一个请求仍然得到所存储的复制,而下一个则在之后的请求的背景中再次使页面恢复. 因此,一个公布的更改会在10分钟内显示在人们打开的一页上,一个没有人打开更长的一页再次显示它的旧副本. 这一拖延(例如晚间换起旗帜)被接受。 从不 `force-static` 在 Next.js 上: 永不过期的一页会保留它先完成的.

```ts
// src/proxy.ts
import { isAssignmentsRoutePath, isDraftRoutePath, rewriteToAssignmentsRoute /* … */ } from "@decocms/nextjs/proxy";

export async function proxy(request: NextRequest) {
  const { pathname } = request.nextUrl;
  if (isDraftRoutePath(pathname) || isAssignmentsRoutePath(pathname)) return new NextResponse(null, { status: 404 });
  const draft = await decideDraft(proxyCms, request, preview);
  const visitor = decideVisitor(request, draft);
  const assigned = isCmsPage(pathname) ? await rewriteToAssignmentsRoute(proxyCms, request, draft, visitor) : null;
  if (assigned) return applyVisitor(applyDraft(assigned, draft), visitor);
  const assignments = await decideAssignments(proxyCms, draft, visitor);
  const headers = assignmentsRequestHeaders(visitorRequestHeaders(draftRequestHeaders(request, draft), visitor), assignments);
  const response = rewriteToDraftRoute(request, draft, visitor, assignments) ?? NextResponse.next({ request: { headers } });
  return applyVisitor(applyDraft(response, draft), visitor);
}

// Next's own files never go through the proxy: rewritten, every script and style would be a 404.
export const config = { matcher: ["/((?!_next/|favicon.ico).*)"] };
```

```tsx
// src/app/%5Fassignments/[assignments]/[[...path]]/page.tsx: every CMS page (a literal `_assignments` folder never routes)
import { assignedClient } from "@decocms/nextjs/server";

export const revalidate = 600; // 10 minutes; never force-static
export async function generateStaticParams() {
  return []; // no path at build time: each renders on its first request, then is cached
}
export default async function Page({ params }) {
  const { assignments, path } = await params;
  const client = await assignedClient(cms, assignments);
  if (!client) notFound();
  // … match the path and resolve the page through `client`, as on any page …
}
```

-   **部分内容**: 保存的每个测试 `experiments` 阻止或关闭访客 和所有被拯救的运动 `campaigns` 块运行或现在不运行( n)`readAssignments` ),作为 `assignmentsSegment` 写道: `-` 没有,否则是base64url,每组任务1个拼写. 每一次测试的同一面访问者都会得到相同的路径;访问者的ID从来没有在其中,被重写的请求既没有带访问者,也没有带草稿头. 一场运动的开始或结束使每个访客都走上了新的道路.
-   **页面使路径名称**数字 : `await assignedClient(cms, segment)` 正在建设 `cms.client({ experiments, campaigns })` 每一个测试和运动都以片段的名称命名,没有访客,一个客户事先完全决定了,所以这个侧面的每个访客都做同一页. 该页面从不检查竞选日期或卷起测试本身. 现在的测试 以0% 保持关闭任何片段名称。 下一页在后面( 重新验证) 显示相同的测试和运动 .
-   **路由信任其代理撰写的路由**: 代理回复直接点击 `/_assignments/…` 和404一样 `/_draft/…`,因此在代理机后面,只有它自己的重写才能到达路由. 以其他方式到达页面的请求( 代理) `matcher` 或一个没有代理的站点)使测试和运动其路径名称: `assignedClient` 只保留测试的0%, 测试或活动的内容没有, 返回 `null` (a 404) 对于一个段,代理从来不写。 哪些路线通过代理, 和如何保护其他人, 是网站的呼声。 离开而不是回答 404 个事项, 因为下一个缓存在路径下也有一个 404 个: 代理服务器看到新发布的内容仍然在生成之前所写的路径 .
-   **URL 请求保持隐私**: 当内容保存测试或运动时, 重写标记响应 `Cache-Control: private, no-cache`。下一个是每个路径和任务集保存一个缓存页面,但 `/shoes` 所以在前面的CDN 绝不能保留Next的ISR `s-maxage` 硂.
-   **缓存页面不读取请求**数字 : `headers()`, (中文(简体) ), `cookies()` 或者说 `searchParams` 路线中的任意位置( 包括其布局, 因此没有) `bindDraft` (在那里)让Next在每次请求时,而不是缓存它,以及一个客户部分呼叫 `useSearchParams()` 使客户端达到最近的 `<Suspense>`。 。 。 . `force-static` 用于通过将页面空值交接来隐藏两者;随着ISR,页面会像任务一样从路径中取出它所需要的.
-   **这里永远不会重写草稿和预览**: 起草的请求会转到动态草稿路由, 因此没有预览在 Next 的缓存中登陆 .
-   **路径**:只有CMS的页面(`isCmsPage` 上面是网站自己的: 应用程序自己的路线,例如 `/blog` 这里,像以前一样渲染. `draftProxy(proxyCms, { assignments: (request) => isCmsPage(request.nextUrl.pathname) })` 对于一个没有自己代理的网站来说也是如此.

`examples/nextjs-binding-smoke` 在寄存器中运行它:在测试的对面有两个访客获得不同的路径,两个在同一侧得到一个缓存条目(`x-nextjs-cache: HIT`),路线为600秒ISR并打出一个键 `/_assignments/…` 路径为 404 .

### 草稿主机

链接草案( A)`?__draft=`在 CMS 允许的主机上进行预览,其中 `cms.readVersion` 检查: 地址 Studio 写入当前发行的元数据 (`previewHosts` 内 `latest.json`,读取 `createCMS`是因为 `site`),加 (中文(简体) ) `createCMS({ preview: { hosts } })`。网站没有列出其他内容。 没有列表, 每个主机都会预览: 没有的网站 `latest.json` 尚未在CDN上发布,或者在 Studio 撰稿前发布 `previewHosts` (它下一次出版时会写列表),内容没有 `site` 除非 `preview.hosts` 列出主机( 如 `["localhost"]`) (中文(简体) ). 若为 `latest.json` 无法读取( 网络错误, 5xx, 错误的文件) , 预览会保持关闭 `preview.hosts`,直到读取成功。 接待者是来访者要求访问者`x-forwarded-host`,则 `host`); 代理和 `bindDraft` 问同一个CMS。 在可能不预览的主机上,该页面会使发布; `?__draft=off` 仍然结束任何预览 .

## 版式

```tsx
import { StudioBridge } from "@decocms/nextjs";

<body>
  {children}
  <StudioBridge site="my-store" />
</body>
```

工作室的起源是包自有的,因此桥只取站名. v7's "." 默认情况下,编辑快捷键已启动(`editShortcut={false}` 关了它,和 `nonce` 是可选的。 桥只为v8:v7被设定的处理器(`scrollToComponent`, (中文(简体) ), `editor::rerender`)已消失,所以页面上没有任何脚本可以比较窗口和 `top` 或者说 `parent`,并重写 HTML 中“帧-bushing”代码的测试跑取器,其代理(Cypress's) `modifyObstructiveCode`)服务于字节的页面字节.

该桥还将 Studio 频道挂在每一页上,制作内容包括: 一个小的内线脚本(约0.7 kB gziped),工作室通过它将自己的编辑码(一保存后的部分线框,页面互换)加载到页面上. 这是工作室在页面中运行代码的唯一方式:桥面评价没有脚本工作室发送. 该页面信任一份确切的工作室起源列表: `studioOrigins` 当给与, 否则 `DECO_STUDIO_ORIGIN` 环境变量,逗号分隔(本地工作室,例如 `http://localhost:3000`)),其他工作室的出品和出品起源(出品人`DEFAULT_STUDIO_ORIGINS`) (中文(简体) ). 框架, 页面帖 `{ type: "deco:ready" }` 每一个都作为目标来源(只有其中之一的家长收到),并且只有在工作室的回答时,才会导入一个模块, `{ type: "deco:load", url }`,来自其中之一,并在该消息的来由上命名一个URL;不是由任何其他来源设定,也不是由其他来源设定,它什么都不做。 有内容安全政策的网站通过 `withStudioCsp(directives)`,将同一列表添加到 `script-src` (和a) `frame-ancestors` 与工作室, 当政策没有: `headers: [{ source: "/:path*", headers: [{ key: "Content-Security-Policy", value: withStudioCsp("script-src 'self' 'unsafe-inline'; object-src 'none'").join("; ") }] }]`,或网站代理中相同. 内线剧本取自网站 `nonce`。信件和模块类型在 `@decocms/blocks/protocol`。 。 。 .

在不位于 Studio 帧的一页上,"""(或 Ctrl+Shift+E)打开了 Studio 编辑器的一页,而 Ctrl 或 Cmd+" 在一个新的分页上打开; Studio 请一个没有签名的访客先签名. 要打开正确的一页,每个CMS页面告诉桥其路径模板:根布局会停留在通航之间,因此该页面使标记在它所解决的部分旁边:

```tsx
import { StudioPage } from "@decocms/nextjs";

const match = matchRoute(pathname, { routes: pages });
// …
return <>{sections}<StudioPage pathTemplate={match.entry.path} /></>;
```

它使一个 `<meta>` 反应位置在 `<head>`,所以页面本身的标记不变. 没有它,工作室从URL中选择页面.

## 名称和工作室的起源

对于一个在自己的代码中需要它们的网站(一条设置自己标题的路线,即它自己写的CSP), `@decocms/nextjs` 导出代理、页面和 `withDeco` 使用: `DRAFT_PARAM` (单位:千美元)`__draft`, (中文(简体) ), `DRAFT_COOKIE` (单位:千美元)`__deco_draft`, (中文(简体) ), `VERSION_HEADER` (单位:千美元)`x-deco-version`, (中文(简体) ), `VISITOR_HEADER` (单位:千美元)`x-deco-visitor`, (中文(简体) ), `ASSIGNMENTS_HEADER` (单位:千美元)`x-deco-assignments`, (中文(简体) ), `draftResponseHeaders(version)`, (中文(简体) ), `STUDIO_ORIGINS`, (中文(简体) ), `STUDIO_FRAME_ANCESTORS`, (中文(简体) ), `isStudioOrigin(origin)`, (中文(简体) ), `DEFAULT_STUDIO_ORIGINS`, (中文(简体) ), `studioOrigins(option?)` 财务报告和审定财务报表 `withStudioCsp(directives, options?)`。它们具有与 `@decocms/tanstack`'s;每个装订都保存自己的副本,从不进口对方.

## 下一个。配置

```js
const { withDeco } = require("@decocms/nextjs/config");
module.exports = withDeco({ images: { loader: "custom", loaderFile: "./src/image-loader.ts" } });
```

`withDeco` 将 v7 的两条草案头规则放在您自己的前面( a) `?__draft=` 查询,或 cookie 草稿: `max-age=0, no-cache, must-revalidate`, (中文(简体) ), `Vary: Cookie`, noindex)并添加 Studio的出处到 `allowedDevOrigins`。每个都可以关闭: `withDeco(config, { draftHeaders: false, studioOrigins: false })`下一组 `Cache-Control` 财务报告和审定财务报表 `Vary` 本身在动态页面上,所以仅 `X-Robots-Tag` 一定能从这些规则中到达 `applyDraft` 将所有三个放在它的反应上.

## 请求参数

```ts
// src/instrumentation.ts (or instrumentation.ts at the root, next to app/)
export { register } from "@decocms/nextjs/instrumentation";
```

下一步,j 已经衡量它所服务的每一项请求:每个请求一个根本跨度(`BaseServer.handleRequest`),以状态,方法和路由模板结束. `register` 给 下一个是追踪器提供商,其唯一工作就是这个范围:当它结束时,请求会转到CMS的遥测仪上作为 `http.server.request.duration` (通过) `recordServerRequest` 从 `@decocms/blocks/metrics`) (秒,与上游客户相同的桶" `http.client.request.duration`在其它东西旁边 `createCMS` 发送。 没有间距被导出到任何地方, 下一个间距要求的每一个间距都是共享的非记录间距 。 没有遥测目的地( 无) `token` 没有 `endpoint`无所记录.

| 标签 | 数值 |
| --- | --- |
| `http.route` | 下一个路由模板 : `/[[...path]]`, (中文(简体) ), `/blog`, (中文(简体) ), `/_draft/[[...path]]`。一个RSC请求在其页面路径下计数. `unmatched` 当下一个名称无时( 边缘路由) `next start`(中文(简体) ) |
| `http.request.method` | `GET`, (中文(简体) ), `POST`,...; 任何其他为 `_OTHER` |
| `status_class` | `2xx` . `5xx`; 发出的请求是 `5xx` |
| `cache` | `DRAFT` 草稿(代理人转交) `x-deco-version`,或请求被重写到 `/_draft`),否则 `BYPASS`:下一个决定自己的缓存(`x-nextjs-cache`在答复中,跨度从未看到 |

-   `@opentelemetry/api` 是可选的对等点 : `register` 使用相同的副本 Next does (您安装时的, 否则 Next 的已编译) , 如果两者都未加载, 则什么都不做 .
-   **您自己的 OpenTelection 设置** (单位:千美元)`@vercel/otel`, (中文(简体) ), `NodeSDK`:只有一个跟踪提供者可以注册,所以 `register` 别管你的了 记下如何结合他们 在您的处理器中添加 : `registerOTel({ serviceName, spanProcessors: ["auto", serverRequestSpanProcessor()] })`。 。 。 .
-   **代理服务器**: 在 `next start` 接下来通过自己请求的跨度运行代理;该跨度不计算,代理手接的请求就是. 代理自制的响应( 重定向, 404 为直接 `/_draft` (按下)从不到达一页,也不计算.
-   **边缘运行时间**数字 : `register` 什么都没有做。 下 `next start` 边缘路由仍由服务它的Node.js服务器测量(`unmatched`,没有模板);在一个独自运行 Edge 函数的宿主上,没有什么可以衡量它们.

## 图像

```ts
// src/image-loader.ts
import { vtexCatalogWebp, vtexFileManager } from "@decocms/apps-vtex/image"; // your platform's helpers, if any
import { createImageUrl, decoCdn } from "@decocms/blocks/image";
import { createDecoImageLoader, nextImageOptimizer } from "@decocms/nextjs/image-loader";

const imageUrl = createImageUrl({
  providers: [
    vtexCatalogWebp(),
    vtexFileManager({ via: "query" }),
    decoCdn({ quality: "high", fit: "contain", layout: "quality-last" }),
  ],
});
export default createDecoImageLoader(imageUrl, { fallback: nextImageOptimizer });
```

装货员不知道商业平台:站点列出其平台的帮手(`@decocms/apps-vtex/image`, (中文(简体) ), `@decocms/apps-shopify/image`)在Deco CDN之前,第一个取出源的提供者会制作它的URL. 任何其他来源到 `fallback` (单位:千美元)`nextImageOptimizer` 使用 Next 的自定义 `/_next/image`),或者回来时没有改变. 有了上面的提供者, 下一个 storefront 的当前加载器 URL 就会为字节出字节(`tests/nextjs-image-loader.golden.test.ts` 除了内容中已经修改的Deco CDN URL:现在正在修改其内容 `src` 而不是成为 `src=image`。 。 。 .

`examples/nextjs-binding-smoke` 在寄存器中,是一个完整的应用程序, 及其 `bun run smoke` 检查整个流量 `next start`。 。 。 .

## 常见问题

### @decocms/nextjs 是什么？

Deco CMS for any Next\.js App Router app: 代理服务器和页面中的预览草稿,预览徽章, Studio Bridge, 有Deco \(\) 和一个下一张/图像加载器

### 如何安装 @decocms/nextjs？

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

### @decocms/nextjs 支持 TypeScript 吗？

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

### @decocms/nextjs 支持 ESM 还是 CommonJS？

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

### @decocms/nextjs 需要什么版本的 Node\.js？

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

### @decocms/nextjs 可以商用吗？

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

### @decocms/nextjs 的下载量有多少？

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

### @decocms/nextjs 还在维护吗？

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

