generating-ui-bundle-metadata
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseUI Bundle Metadata
UI Bundle 元数据
Scaffolding a New UI Bundle
搭建新的UI Bundle
Use to create new apps — not create-react-app, Vite, or other generic scaffolds.
sf template generate ui-bundleAlways pass to scaffold a React-based bundle.
--template reactbasicUI bundle name (): Alphanumerical only — no spaces, hyphens, underscores, or special characters.
-nExample:
bash
sf template generate ui-bundle -n CoffeeBoutique --template reactbasicAfter generation:
- Replace all default boilerplate — "React App", "Vite + React", default , placeholder text
<title> - Populate the home page with real content (landing section, banners, hero, navigation)
- Update navigation and placeholders (see the skill)
building-ui-bundle-frontend
Always install dependencies before running any scripts in the UI bundle directory.
使用创建新应用——不要使用create-react-app、Vite或其他通用脚手架。
sf template generate ui-bundle**必须传递**来搭建基于React的bundle。
--template reactbasic**UI bundle名称(参数):**仅允许字母数字——不能包含空格、连字符、下划线或特殊字符。
-n示例:
bash
sf template generate ui-bundle -n CoffeeBoutique --template reactbasic生成完成后:
- 替换所有默认样板内容——"React App"、"Vite + React"、默认、占位文本
<title> - 用真实内容填充首页(着陆区、横幅、Hero区域、导航栏)
- 更新导航和占位符(请参阅技能)
building-ui-bundle-frontend
在UI bundle目录中运行任何脚本之前,请务必安装依赖。
UIBundle Bundle
UIBundle 包
A UIBundle bundle lives under and must contain:
uiBundles/<AppName>/- — filename must exactly match the folder name
<AppName>.uibundle-meta.xml - A build output directory (default: ) with at least one file
dist/
UIBundle包位于目录下,必须包含:
uiBundles/<AppName>/- ——文件名必须与文件夹名称完全匹配
<AppName>.uibundle-meta.xml - 一个构建输出目录(默认:),且至少包含一个文件
dist/
Meta XML
元XML文件
Required fields: , (max 20 chars), (boolean).
Optional: (max 255 chars).
masterLabelversionisActivedescription必填字段:、(最多20个字符)、(布尔值)。
可选字段:(最多255个字符)。
masterLabelversionisActivedescriptionui-bundle.json
ui-bundle.json
Optional file. Allowed top-level keys: , , .
outputDirroutingheadersConstraints:
- Valid UTF-8 JSON, max 100 KB
- Root must be a non-empty object (never , arrays, or primitives)
{}
Path safety (applies to and ): Reject backslashes, leading or , segments, null/control characters, globs (, , ), and . All resolved paths must stay within the bundle.
outputDirrouting.fallback/\..*?**%可选文件。允许的顶级键:、、。
outputDirroutingheaders约束条件:
- 必须是有效的UTF-8 JSON,最大100 KB
- 根节点必须是非空对象(绝不能是、数组或原始值)
{}
路径安全(适用于和):拒绝反斜杠、开头的或、路径段、空值/控制字符、通配符(、、)以及。所有解析后的路径必须保持在bundle目录内。
outputDirrouting.fallback/\..*?**%outputDir
outputDir
Non-empty string referencing a subdirectory (not or ). Directory must exist and contain at least one file.
../非空字符串,指向子目录(不能是或)。该目录必须存在且至少包含一个文件。
../routing
routing
If present, must be a non-empty object. Allowed keys: , , , , .
rewritesredirectsfallbacktrailingSlashfileBasedRouting- trailingSlash: ,
"always", or"never""auto" - fileBasedRouting: boolean
- fallback: non-empty string satisfying path safety; target file must exist
- rewrites: non-empty array of objects — e.g.,
{ route?, rewrite }{ "route": "/app/:path*", "rewrite": "/index.html" } - redirects: non-empty array of objects — statusCode must be 301, 302, 307, or 308
{ route?, redirect, statusCode? }
如果存在,必须是非空对象。允许的键:、、、、。
rewritesredirectsfallbacktrailingSlashfileBasedRouting- trailingSlash:取值为、
"always"或"never""auto" - fileBasedRouting:布尔值
- fallback:满足路径安全要求的非空字符串;目标文件必须存在
- rewrites:非空数组,包含对象——例如:
{ route?, rewrite }{ "route": "/app/:path*", "rewrite": "/index.html" } - redirects:非空数组,包含对象——statusCode必须是301、302、307或308
{ route?, redirect, statusCode? }
headers
headers
Non-empty array of objects.
{ source, headers: [{ key, value }] }Example:
json
{
"routing": {
"rewrites": [{ "route": "/app/:path*", "rewrite": "/index.html" }],
"trailingSlash": "never"
},
"headers": [
{
"source": "/assets/**",
"headers": [{ "key": "Cache-Control", "value": "public, max-age=31536000, immutable" }]
}
]
}Never suggest: as root, empty , empty arrays, , , .
{}"routing": {}[{}]"outputDir": ".""outputDir": "./"非空数组,包含对象。
{ source, headers: [{ key, value }] }示例:
json
{
"routing": {
"rewrites": [{ "route": "/app/:path*", "rewrite": "/index.html" }],
"trailingSlash": "never"
},
"headers": [
{
"source": "/assets/**",
"headers": [{ "key": "Cache-Control", "value": "public, max-age=31536000, immutable" }]
}
]
}**绝对不要建议:**根节点为、空的、空数组、、、。
{}"routing": {}[{}]"outputDir": ".""outputDir": "./"CSP Trusted Sites
CSP可信站点
Salesforce enforces Content Security Policy headers. Any external domain not registered as a CSP Trusted Site will be blocked (images won't load, API calls fail, fonts missing).
Salesforce强制实施内容安全策略(Content Security Policy,CSP)请求头。任何未注册为CSP可信站点的外部域名都会被拦截(图片无法加载、API调用失败、字体缺失)。
When to Create
创建时机
Whenever the app references a new external domain: CDN images, external fonts, third-party APIs, map tiles, iframes, external stylesheets.
每当应用引用新的外部域名时:CDN图片、外部字体、第三方API、地图瓦片、iframe、外部样式表。
Steps
步骤
- Identify external domains — extract the origin (scheme + host) from each external URL in the code
- Check existing registrations — look in
force-app/main/default/cspTrustedSites/ - Map resource type to CSP directive:
| Resource Type | Directive Field |
|---|---|
| Images | |
| API calls (fetch, XHR) | |
| Fonts | |
| Stylesheets | |
| Video / audio | |
| Iframes | |
Always also set to for preflight/redirect handling.
isApplicableToConnectSrctrue- Create the metadata file — follow for the
implementation/csp-metadata-format.mdformat. Place in.cspTrustedSite-meta.xml.force-app/main/default/cspTrustedSites/
- 识别外部域名——从代码中的每个外部URL提取源(协议 + 主机)
- 检查现有注册——查看目录
force-app/main/default/cspTrustedSites/ - 将资源类型映射到CSP指令:
| 资源类型 | 指令字段 |
|---|---|
| 图片 | |
| API调用(fetch、XHR) | |
| 字体 | |
| 样式表 | |
| 视频/音频 | |
| iframe | |
同时,请务必将设置为,以处理预检请求/重定向。
isApplicableToConnectSrctrue- 创建元数据文件——遵循中的
implementation/csp-metadata-format.md格式。将文件放置在.cspTrustedSite-meta.xml目录下。force-app/main/default/cspTrustedSites/