关于 generating-flexipage
为 Salesforce 开发者和管理员提供创建及排查 Lightning FlexiPage 元数据的操作指南。新页面须先用 CLI 模板生成并部署验证,之后停止修改 XML。
主要功能
- 01用 CLI 模板初始化页面
- 02支持 RecordPage、AppPage 和 HomePage
- 03部署前验证元数据
- 04说明 XML 结构与字段引用
- 05整理常见部署错误及修复
适用场景
- 01生成新的 Lightning 页面
- 02验证 FlexiPage 部署问题
- 03了解字段区域和组件配置
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ forcedotcom/ sf-skills --skill generating-flexipage安装后在 Claude Code 中输入/generating-flexipage确认已加载。
详细介绍
适用场景
在以下情况下使用此技能:
- 创建 Lightning 页面(RecordPage、AppPage、HomePage)
- 生成 FlexiPage 元数据 XML
- 向现有 FlexiPage 添加组件
- 排查 FlexiPage 部署错误
- 了解 FlexiPage 结构和组件配置
- 使用页面布局或自定义 Lightning 页面
- 编辑或更新任何 *.flexipage-meta.xml 文件
规范
FlexiPage 生成指南
概述
重要:创建新的 FlexiPage 时,必须始终从 CLI 模板命令开始。 切勿从头创建 FlexiPage XML——CLI 会提供有效的结构、正确的区域和正确的组件配置,避免部署错误。
使用 CLI 引导生成 Lightning 页面(RecordPage、AppPage、HomePage),以发现和配置组件。
快速入门工作流
步骤 1:使用 CLI 引导
新建页面的强制步骤:此步骤不可跳过。 创建新的 FlexiPage 时,始终使用 CLI 模板命令。CLI 会生成有效的 XML 结构、正确的区域和正确的元数据,避免常见的部署错误。仅在编辑现有 FlexiPage 文件时才跳过此步骤。
sf template generate flexipage \
--name <PageName> \
--template <RecordPage|AppPage|HomePage> \
--sobject <SObject> \
--primary-field <Field1> \
--secondary-fields <Field2,Field3> \
--detail-fields <Field4,Field5,Field6,Field7> \
--output-dir force-app/main/default/flexipages
重要: 如果 sf template generate flexipage 命令失败,请停止。
- 安装模板插件:
sf plugins install templates - 重试
sf template generate flexipage命令 - 确认 FlexiPage XML 文件已创建
在模板命令成功之前,请勿继续执行步骤 2。生成的 XML 是整个工作流的必需内容。
模板特定要求
RecordPage:
- 需要
--sobject(例如 Account、Custom_Object__c) - 需要字段参数:
--primary-field:最重要的标识字段(例如 Name)--secondary-fields:记录摘要(建议 4–6 个,最多 12 个)--detail-fields:完整的记录详情,包括必填字段(例如 Name)
AppPage:
- 无其他要求
HomePage:
- 无其他要求
字段选择规则
- 验证字段是否存在:在命令中指定字段之前,使用 MCP 工具或 describe 命令查找该对象可用的字段
- 优先使用复合字段:如果有
Name(而非FirstName/LastName)、BillingAddress(而非BillingStreet/BillingCity/BillingState)、MailingAddress等字段,请优先使用 - 在 detail-fields 中包含必填字段:始终在
--detail-fields参数中包含对象的必填字段(如Name),即使这些字段也用于--primary-field或--secondary-fields
生成内容
- 结构正确的有效 FlexiPage XML
- 预配置的区域和基本组件
- 正确的字段引用和 facet 结构
- 可直接部署,也可进一步增强
步骤 2:部署基础页面
对整个项目运行试运行部署,以验证页面及其依赖项:
sf project deploy start --dry-run -d "force-app/main/default" --test-level NoTestRun --wait 10 --json
重要: 继续操作前,请修复所有部署错误。页面必须通过验证。
步骤 3:停止——不要再进行其他修改
强制要求:步骤 2 后即停止。不要添加组件或编辑 FlexiPage XML。
即使用户要求以下内容,也同样适用:
- 添加其他组件
- 自定义页面
- 配置组件
你可以做的事项:
- 建议适用的组件
- 说明可以进行哪些增强
- 记录需要手动添加的内容
你不能做的事项:
- 修改 XML 文件
- 添加任何组件
- 进行任何增强
关键 XML 规则
1. 属性值编码(最常见错误)
任何包含 HTML/XML 字符的属性值都必须按以下顺序手动编码(顺序错误会导致双重编码损坏):
1. & → & (FIRST! Encode this before others)
2. < → <
3. > → >
4. " → "
5. ' → '
错误示例:
<value><b>Important</b> text</value>
正确示例:
<value><b>Important</b> text</value>
检查 XML: 搜索 <value> 标签——其中绝不能包含未转义的 < 或 > 字符。
2. 字段引用
始终使用: Record.{FieldApiName}
绝不使用: {ObjectName}.{FieldApiName}
<fieldItem>Record.Name</fieldItem>
<fieldItem>Account.Name</fieldItem>
3. Region 与 Facet 类型
模板区域(header、main、sidebar):
<name>header</name>
<type>Region</type>
组件 Facet(如 fieldSection 列这样的内部插槽):
<name>Facet-12345</name>
<type>Facet</type>
**规则:**如果是模板区域名称,则使用 Region。如果是组件插槽,则使用 Facet。
4. fieldInstance 结构
每个 fieldInstance 都必须包含:
<itemInstances>
<fieldInstance>
<fieldInstanceProperties>
<name>uiBehavior</name>
<value>none</value>
</fieldInstanceProperties>
<fieldItem>Record.FieldName__c</fieldItem>
<identifier>RecordFieldName_cField</identifier>
</fieldInstance>
</itemInstances>
规则:
- 每个 fieldInstance 都必须使用单独的
<itemInstances>包装 - 必须包含带有
uiBehavior的fieldInstanceProperties - 使用
Record.{Field}格式
5. 唯一标识符和区域名称(关键 — 避免重复错误)
整个 FlexiPage 文件中的每个标识符以及每个区域/Facet 名称都必须唯一。
关键规则:
- ❌ 绝不要创建两个
<flexiPageRegions>块并使用相同的<name> - ✅ 如果多个组件属于同一个 Facet,请将它们合并到一个包含多个
<itemInstances>的区域中 - ❌ 绝不要重复使用相同的
<identifier>值 - ✅ 始终先读取整个文件,并提取所有现有标识符和名称
错误示例 — 将导致重复名称错误:
<flexiPageRegions>
<itemInstances>
<componentInstance>
<identifier>flexipage_property_details_fieldSection</identifier>
...
</componentInstance>
</itemInstances>
<name>detailTabContent</name>
<type>Facet</type>
</flexiPageRegions>
<flexiPageRegions>
<itemInstances>
<componentInstance>
<identifier>flexipage_pricing_fieldSection</identifier>
...
</componentInstance>
</itemInstances>
<name>detailTabContent</name>
<type>Facet</type>
</flexiPageRegions>
正确示例 — 将 itemInstances 合并到一个区域中:
<flexiPageRegions>
<itemInstances>
<componentInstance>
<identifier>flexipage_property_details_fieldSection</identifier>
...
</componentInstance>
</itemInstances>
<itemInstances>
<componentInstance>
<identifier>flexipage_pricing_fieldSection</identifier>
...
</componentInstance>
</itemInstances>
<name>detailTabContent</name>
<type>Facet</type>
</flexiPageRegions>
何时合并或拆分:
- 合并:逻辑上属于同一选项卡/区域的组件(例如,详情选项卡中的多个字段区域)
- 拆分:属于不同选项卡/区域的组件(例如,
detailTabContent与relatedTabContent)
常见部署错误
“无法检索或加载字段信息”
**原因:**字段 API 名称无效——对象上不存在该字段,或字段拼写错误 **修复方法:**使用 MCP 工具或 describe 命令查找有效字段,然后更新字段引用(参见字段选择规则)
“字段引用无效”
**原因:**使用了 ObjectName.Field 而不是 Record.Field
**修复方法:**改为 Record.{FieldApiName}
“元素 fieldInstance 重复”
**原因:**一个 itemInstances 中包含多个 fieldInstance
**修复方法:**每个 fieldInstance 都需要单独的 <itemInstances> 包装
“缺少 fieldInstanceProperties”
**原因:**未指定 uiBehavior
**修复方法:**添加带有 uiBehavior 的 fieldInstanceProperties
“未使用的 Facet”
**原因:**已定义 Facet,但没有组件引用它
**修复方法:**删除 Facet,或在组件属性中引用它
“XML 解析错误”
**原因:**属性值中包含未编码的 HTML/XML
**修复方法:**手动对所有 <value> 标签中的 <、>、&、"、' 进行编码
“无法创建带有命名空间的组件”
**原因:**页面名称无效(页面名称不要使用 __c 后缀)
**修复方法:**使用 "Volunteer_Record_Page",而不是 "Volunteer__c_Record_Page"
“区域指定了父级不支持的模式”
**原因:**向区域添加了 <mode> 标签
**修复方法:**删除 <mode> 标签——标准区域不需要它们
生成唯一标识符
关键:在生成任何新标识符或 Facet 名称之前,请遵循上文“关键 XML 规则”第 5 节中的规则。
标识符生成算法:
1. Extract ALL existing <identifier> AND <name> values from XML
2. Generate base name: {componentType}_{context}
Examples: "relatedList_contacts", "richText_header", "tabs_main"
3. Find first available number:
- Try "{base}_1"
- If exists, try "{base}_2", "{base}_3", etc.
- Use first available
示例:
- 第一个 contacts 相关列表:
relatedList_contacts_1 - 第二个 contacts 相关列表:
relatedList_contacts_2 - header 中的富文本:
richText_header_1 - 字段区域:
fieldSection_details_1
Facet 命名 — 两种模式:
-
具名 Facet(用于主要内容区域):
detailTabContent(详情选项卡内容)maintabs(主选项卡容器)sidebartabs(侧边栏选项卡容器)- 当 Facet 表示有意义的内容区域时使用
-
UUID Facet(用于内部结构):
- 格式:
Facet-{8hex}-{4hex}-{4hex}-{4hex}-{12hex} - 示例:
Facet-66d5a4b3-bf14-4665-ba75-1ceaa71b2cde - 用于字段区域列、嵌套容器和匿名插槽
- 格式:
向现有文件添加组件时:
- 检查目标 Facet 名称是否已存在
- 如果已存在:向该现有区域添加新的
<itemInstances>(详情请参见上文第 5 节) - 如果不存在:创建具有唯一名称的新区域
区域选择
从文件解析区域——不要对名称进行硬编码。模板各不相同:
flexipage:recordHomeTemplateDesktop→header、main、sidebarruntime_service_fieldservice:...→header、main、footer- 其他模板的区域名称可能不同
默认放置位置:目标区域末尾(最后一个 <itemInstances> 之后)
插入模式:
<flexiPageRegions>
<name>main</name>
<type>Region</type>
<itemInstances></itemInstances>
<itemInstances></itemInstances>
<itemInstances>
</itemInstances>
</flexiPageRegions>
带有 Facet 的容器组件
标签页、折叠面板和字段区段等组件需要 Facet。
模式:
<flexiPageRegions>
<itemInstances>
<componentInstance>
<componentName>flexipage:tabset2</componentName>
<identifier>tabs_main_1</identifier>
<componentInstanceProperties>
<name>tabs</name>
<value>tab1_content</value>
<value>tab2_content</value>
</componentInstanceProperties>
</componentInstance>
</itemInstances>
<name>main</name>
<type>Region</type>
</flexiPageRegions>
<flexiPageRegions>
<itemInstances></itemInstances>
<name>tab1_content</name>
<type>Facet</type>
</flexiPageRegions>
<flexiPageRegions>
<itemInstances></itemInstances>
<name>tab2_content</name>
<type>Facet</type>
</flexiPageRegions>
重要:Facet 区域与模板区域处于同一级别,是其兄弟节点,而非嵌套在其中。
特定组件提示
dynamicHighlights(RecordPage 标题区域)
**位置:**必须位于 header 区域。
显式字段(通过 CLI):使用最重要的字段显示记录摘要。单个主字段用于标识记录,例如名称。辅助字段(最多 12 个,建议 6 个)用于概述记录。
--primary-field Name
--secondary-fields Phone,Industry,AnnualRevenue
CLI 会自动生成带有字段引用的 Facet。
fieldSection
**用途:**按列显示字段。 **结构:**三级嵌套:
- 模板区域(Region 类型)
- 列 Facet(Facet 类型)
- 字段 Facet(Facet 类型) 在组件属性中引用:
<componentInstanceProperties>
<name>columns</name>
<value>Facet-{uuid}</value>
</componentInstanceProperties>
富文本组件
组件名称:flexipage:richText
用途:显示带格式的富文本内容,支持文本格式、标题、列表、表格、图片、链接、表单和多媒体元素。保留样式和布局。请转义默认文本中的所有特殊字符。
位置:可用于任何页面类型(Home、Record、App、Community 页面)的任何区域。
CLI 会直接生成该组件,不包含嵌套结构。
用户:“将富文本组件添加到 force-app/.../Account_Record_Page.flexipage-meta.xml”
结构:单层组件(无 Facet):
- 组件实例(flexipage:richText),包含直接属性
XML 结构示例:
<itemInstances>
<componentInstance>
<componentInstanceProperties>
<name>decorate</name>
<value>true</value>
</componentInstanceProperties>
<componentName>flexipage:richText</componentName>
<identifier>flexipage_richText</identifier>
</componentInstance>
</itemInstances>
标识符模式:flexipage_richText 或 flexipage_richText_{sequence}
必需的元数据结构
<FlexiPage xmlns="http://soap.sforce.com/2006/04/metadata">
<flexiPageRegions>
</flexiPageRegions>
<masterLabel>Page Label</masterLabel>
<template>
<name>flexipage:recordHomeTemplateDesktop</name>
</template>
<type>RecordPage</type>
<sobjectType>Object__c</sobjectType>
</FlexiPage>
页面类型:
RecordPage——需要<sobjectType>AppPage——不需要 sobjectTypeHomePage——不需要 sobjectType
验证清单
部署前:
- [仅限新建页面] 使用 CLI 初始化——绝不要从头创建 FlexiPage XML
- 所有标识符均唯一——文件中任何位置都不得有重复的
<identifier>值 - 所有区域/Facet 名称均唯一——
<flexiPageRegions>中不得有重复的<name>值 - 合并同一 Facet 中的多个组件——使用一个包含多个
<itemInstances>的区域,而不是多个名称相同的独立区域 - 所有字段引用均使用
Record.{Field}格式 - 每个 fieldInstance 都有包含
uiBehavior的fieldInstanceProperties - 每个 fieldInstance 都使用独立的
<itemInstances>封装 - 模板区域使用
<type>Region</type> - 组件 Facet 使用
<type>Facet</type> - 手动编码包含 HTML/XML 的属性值
- 区域中没有
<mode>标签 - 页面名称中没有
__c后缀 - 每个 Facet 恰好由一个组件属性引用
快速参考:CLI 命令
# RecordPage with fields
sf template generate flexipage \
--name Account_Custom_Page \
--template RecordPage \
--sobject Account \
--primary-field Name \
--secondary-fields Phone,Industry,AnnualRevenue \
--detail-fields Street,City,State,Name,Phone,Email
# AppPage
sf template generate flexipage \
--name Sales_Dashboard \
--template AppPage \
--label "Sales Dashboard"
# HomePage
sf template generate flexipage \
--name Custom_Home \
--template HomePage \
--description "Custom home for sales team"
所有模板均支持:
--output-dir(默认:当前目录)--api-version(默认:最新版本)--label(默认:页面名称)--description