建模 Croct 内容
设计组件和插槽,编写它们的模式,并填充内容定义,使其在模型演变过程中保持有效。模式所能表达的一切在仪表盘可视化编辑器中也存在;JSON 是相同的模型,由手动编写。
心智模型
| 概念 | 含义 | 范围 |
|---|---|---|
| 组件 | 一个可命名的、可重用的模式。只有 structure 和 union 可以是组件(顶级模式)。 | 可在插槽和其他组件之间重用 |
| 常规组件 | 一个具有固定属性集的 structure。 | |
| 联合组件 | 一个包含最多 10 个常规组件的 union;编辑器为每个内容选择一个变体。 | |
| 插槽 | 应用中的占位符(hero 区域、通知栏),与一个组件绑定。为每个区域设置保留默认内容。 | 上下文特定;一个组件可以支持多个插槽 |
| 内容定义 | 保存模式实际值的 JSON,可以是静态值或动态(CQL)值。 |
内容层次,从基础到顶层:插槽默认内容(当没有匹配的体验或实验时显示,对机器人过滤排除的机器人显示,在静态渲染时显示,以及在出错时显示)-> 体验内容(按受众)-> 实验内容(按变体,至少两个变体)-> 内容组(在体验或实验变体内,针对子区段的额外变化)。后备内容存在于应用的源代码中,当获取失败或服务暂停时渲染;CLI 将插槽默认内容下载为后备内容。
决定形状
| 如果你需要... | 使用 |
|---|---|
| 一个固定的布局(各处相同的字段) | 常规组件(structure) |
| 编辑器可在其中选择的变体(文本横幅 vs 图片横幅 vs 表单横幅) | 引用常规组件的联合组件 |
| 许多地方的一致性(各处使用的 CTA 按钮) | 一个单独的组件,使用 {"type": "reference", "id": "..."} 嵌入 |
| 一个地方的灵活性(标题 + 图片对) | 嵌套的 structure 属性或原始类型,而不是新建组件 |
| 一个包含几个独立部分的页面 | 每个部分一个组件和一个插槽,而不是一个巨大的组件 |
| 一组预定义的选项 | 带 choices 的 text(枚举) |
| 图片、视频、音频或文档上传 | 引用 @croct/file(文件限制为 5 MB;对于较长的视频,考虑使用 url 文本属性) |
| 在工具栏编辑器中编辑的格式化文本 | 引用 @croct/richText |
| 纯文本字段中的轻量格式化 | text + 应用中的 Markdown 解析器(参见下面的 Markdown) |
| 仅用于计算其他值的值(例如,动态变量) | 带有 "private": true 的属性 |
来自文档的经验法则:问自己“我需要灵活性还是一致性?” 灵活性 -> 结构属性。一致性 -> 新组件。
工作流程
- 列出页面的各个部分;每个独立放置的部分成为一个插槽。
- 对于每个插槽,选择一个常规或联合组件。在结构需要保持一致的地方重用现有组件。
- 编写模式:属性带有
type、label、description、position和optional(内容可能缺失的情况)。根据实际 UI 约束添加验证(maximumLength、minimum、pattern、allowedTypes、列表上的maximumLength)。 - 在添加嵌套前检查限制(见下文)。计算复杂度评分。
- 为每个插槽和每个支持的区域设置编写默认内容定义。
- 如果组件已在用,则在破坏性变更时预期新版本;在更新受影响的内容后,在应用中升级插槽版本(参见版本控制)。
模式骨架
一个常规组件是一个 structure。每个属性将其模式包装在 type 中:
{
"type": "structure",
"title": "CTA 按钮",
"description": "一个链接到页面的行动号召按钮。",
"attributes": {
"label": {
"label": "标签",
"description": "按钮上显示的文本。",
"position": 0,
"type": {
"type": "text"
}
},
"link": {
"label": "链接",
"description": "要链接到的页面的 URL。",
"position": 1,
"type": {
"type": "text"
}
}
}
}
一个联合组件将组件 ID 映射到引用。键必须等于被引用的 ID:
{
"type": "union",
"types": {
"text-hero": {"type": "reference", "id": "text-hero"},
"image-hero": {"type": "reference", "id": "image-hero"}
}
}
在应用中,联合插槽内容是一个判别联合:每个变体都有一个 _type 属性,设置为组件 ID(上面的 text-hero 或 image-hero)。基于 _type 分支来渲染它;请参阅 croct-integrate-sdk 技能。
属性类型一览
| 仪表盘类型 | Schema JSON |
|---|---|
| 文本 | {"type": "text"} (+ minimumLength, maximumLength, pattern) |
| 多行文本 | {"type": "text", "format": "multiline"} |
| URL | {"type": "text", "format": "url"} |
| 颜色 | {"type": "text", "format": "color"} |
| 日期 / 时间 | {"type": "text", "format": "instant"} (也支持 local-date, local-time, local-date-time, zoned-date-time) |
| 枚举 | {"type": "text", "choices": {"left": {"label": "Left"}}} |
| 富文本 | {"type": "reference", "id": "@croct/richText", "properties": {}} |
| 文件 | {"type": "reference", "id": "@croct/file", "properties": {}} |
| 数字 | {"type": "number"} (+ integer, minimum, maximum) |
| 布尔 | {"type": "boolean"} (+ label.true, label.false, default) |
| 列表 | {"type": "list", "items": {...}} (+ itemLabel, minimumLength, maximumLength) |
| 结构 | {"type": "structure", "attributes": {...}} |
| 组件 | {"type": "reference", "id": "<component-id>"} |
format 和 choices 不能与除 type 之外的任何其他文本属性组合使用。完整的属性列表、默认值和限制:references/schema.md。
模式限制
| 限制 | 值 |
|---|---|
| 每个结构的属性数 | 30 |
| 嵌套深度 | 6 级 |
| 联合中的组件数 | 10 |
| 模式复杂度评分 | 50 |
列表项(模式默认 maximumLength) | 30 |
文本 maximumLength | 单行 300;多行和 URL 1000(隐式上限:纯 text 不能将 format 与 maximumLength 结合使用;富文本可以) |
文本 choices | 20 |
| 文件大小 | 5 MB (5242880 字节) |
| 标签 / 描述 | 60 / 160 字符 |
复杂度评分:structure = 1 + 其属性数;list = 1 + 其项目类型;primitive = 1;union = 其最复杂的成员;reference = 所引用的组件。一个包含标题、图片和价格的产品列表评分为 5。
内容定义骨架
每个值都是 {"type": "<content type>", "value": {"type": "static" | "dynamic", ...}}。结构嵌套 attributes;列表包含 items;联合内容是一个结构,其 name 设置为联合键。
{
"type": "structure",
"attributes": {
"message": {
"type": "text",
"value": {"type": "static", "value": "欢迎,{{variable}}!"}
},
"variable": {
"type": "text",
"value": {
"type": "dynamic",
"expression": "user's name",
"nullable": true,
"default": "guest"
}
}
}
}
expression是 CQL(参见croct-cql技能)。default在求值失败、返回null或返回不兼容类型时使用。nullable必须与模式中的属性optional标志匹配。- 将像
variable这样的辅助属性在模式中标记为"private": true,使其不包含在交付给应用的内容中。 - 内容限制:最多 30 个列表项,最多 10 个动态值,复杂度评分 50。
- 动态值是 Scale 计划功能;本地化是附加功能。
占位符、相对路径、后备和每种内容类型:references/definition.md。
本地化
- 区域设置是按工作区配置的。本地化是一个附加功能。
- 为每个受支持的区域设置为每个插槽提供默认内容。没有默认内容的区域设置将使用默认区域设置的内容。体验和实验也按区域设置持有内容;没有特定区域设置内容的体验将为该区域设置提供插槽的默认内容。
- 当请求的区域设置缺失时的后备行为:SDK 文档说是工作区的默认区域设置;内容 API 文档说是插槽的默认区域设置。文档存在分歧;请说明这一情况,而不是自行选择其一。
- 在代码中请求区域设置:使用
preferredLocale(每次获取)或defaultPreferredLocale(应用全局),或在 Next.js/Hydrogen 中使用localeResolver;参见croct-integrate-sdk技能。 croct.json包含defaultLocale和locales;croct install按插槽、版本和区域设置下载后备内容。参见croct-use-cli技能。
版本控制与破坏性变更
- 更改组件模式,例如添加属性或更改现有属性(文档的示例)。
- 当更改以可能破坏应用的方式影响内容结构时,Croct 会创建一个新版本,并继续向应用提供旧版本。
- 更新所有受影响的插槽和体验的内容(仪表盘会标记它们)。
- 在应用代码中升级插槽版本,例如
fetchContent('home-hero@2')。
应该做:
- 在应用代码中固定插槽版本(
home-hero@1)。无版本 ID 使用最新版本,因此破坏性变更会立即生效并可能破坏应用。 - 也更新体验和实验内容,而不仅仅是插槽默认内容。
- 在更改后保持后备内容同步(
croct-use-cli技能涵盖了同步)。
不应该做:
- 假设哪些编辑是破坏性的。文档没有列出它们;依赖仪表盘的插槽影响警告。
重构
| 情况 | 技术 |
|---|---|
| 一个更改应适用于大多数(但不是所有)用法 | 复制并修改:复制组件,将少数例外指向副本,然后更改原版 |
| 一个更改应仅适用于少数用法 | 复制并替换:复制,更改副本,将这些用法指向副本 |
| 组件达到最大嵌套级别 | 扁平合并:将嵌套结构的属性合并到父级,然后更新所有使用它的地方的内容 |
| 组件接近复杂度限制 | 拆分为由单独插槽渲染的更小组件 |
| 结构达到 30 个属性的限制 | 指导(文档对此没有指南):将相关属性分组到嵌套结构中,保持在 6 级嵌套之内,或者拆分为单独的组件和插槽。固定的插槽版本(home-hero@1)在你迁移期间保持线上应用使用旧模式 |
详细信息、步骤和最佳实践:references/design-and-refactoring.md。
文本属性中的 Markdown
- 富文本(
@croct/richText)存储由工具栏编辑器生成的 Markdown;使用allowedFormatting限制它。 - 纯
text属性存储原始字符串。要在此处支持 Markdown,在应用中解析它,例如使用@croct/md-lite(粗体、斜体、删除线、代码、链接、图片、段落)。 - 保持简单的格式。将 CTA 标签、URL 和产品数据建模为单独的属性。
- 在属性
description中说明支持的语法,例如“支持用于 bold、italic 和 links 的 Markdown 语法。”
渲染代码:references/design-and-refactoring.md。
常见陷阱
- 为单个标题或图片创建组件。应使用原始类型或结构。
- 通用名称(“产品卡片”)。应使用目的性名称(“产品功能列表”)。
union的types键与被引用的组件 ID 不同:模式无效。- 超过一个
choices条目带有"default": true:模式无效。 - 没有秒的日期/时间值:
10:15无效,10:15:00有效。 - 与模式
optional标志不一致的nullable动态值。 - 当体验的插槽版本与应用版本不同时,预览显示过期内容。
实时文档
- 索引:
https://docs.croct.com/llms.txt - 任何页面作为 Markdown:
https://docs.croct.com/reference/content/schema/introduction.md - 搜索:
https://docs.croct.com/api/search.md?term=<terms>