用途
该技能面向 Storefront Next 的扩展系统,用于构建可插拔的模块化功能。扩展是自包含的功能模块,能够向 Storefront Next 店面添加组件、路由、翻译和上下文提供者,而无需修改核心代码。
主要能力
- 通过 target-config.json 声明扩展如何集成,包括组件和上下文提供者。
- 使用目标点(target points)作为店面布局中的命名插入槽位,扩展通过 targetId 在这些位置插入组件。
- 扩展路由:routes/ 目录中的文件会自动注册为路由。
- 扩展翻译:翻译会根据目录名自动以 extPascalCase 形式命名空间化。
- 集成标记:在核心代码中标记扩展集成点,支持单行标记和块标记。
- 扩展可用性在 src/extensions/config.json 中管理,每个扩展以 SFDC_EXT_* 标记为键。
使用方式
构建前的决策门(先审计基础代码)
扩展适用于添加店面尚未渲染的内容。在搭建扩展前,需确认确实需要它——重复的区块会在每次页面加载、每次测试和每次设计同步中产生成本。
在编写任何扩展代码前运行此门:
- 找到基础。打开 src/routes/ 中的相关路由,追踪它渲染的每个组件。
- 检查你打算添加的每个区块。基础是否已在该位置渲染了等效内容(描述、手风琴、徽章、横幅、标题……)?
- 是 → 不要创建并行组件。通过 token/品牌层(CVA 变体或 brand.css 值)重新样式化,或注入到现有内容的 UITarget 槽位。添加重复区块是 bug,不是功能。
- 否 → 扩展是合理的。继续下面的结构,并在正确的 targetId 注册它。
- 决定缺失内容所属的层:
- 变更是否纯粹是视觉的(颜色、字体、间距)?
- 是 → Token / CVA 变更(brand.css 或组件变体)。无需扩展。
- 否 → 新结构是否仅被一个店面/垂直领域需要?
- 是 → 在 UITarget 槽位使用扩展(本技能)。永远不要编辑核心。
- 否 → 它是共享模式——改为向基础组件添加槽位/render-prop,让每个消费者填充它。
- 变更是否纯粹是视觉的(颜色、字体、间距)?
经验法则:扩展添加缺失的内容;它们从不重建已存在的内容。如有疑问,优先选择 UITarget 槽位或 token 覆盖,而非新组件。
扩展结构
src/extensions/my-extension/
├── target-config.json # 目标配置(组件/提供者)
├── components/ # 扩展组件
├── routes/ # 扩展路由(自动注册)
├── locales/ # 扩展翻译(自动命名空间化)
└── providers/ # 扩展上下文提供者
目标配置
target-config.json 文件声明扩展如何集成:
{
"components": [
{
"targetId": "header.before.cart",
"path": "extensions/my-extension/components/badge.tsx",
"order": 0
}
],
"contextProviders": [
{
"path": "extensions/my-extension/providers/my-provider.tsx",
"order": 0
}
]
}
目标点
目标点是店面布局中的命名插入槽位(例如 header.before.cart)。扩展通过 targetId 在这些点插入组件。
扩展可用性在 src/extensions/config.json 中管理,每个扩展以 SFDC_EXT_* 标记为键。
扩展路由
routes/ 目录中的文件会自动注册为路由:
// src/extensions/my-extension/routes/my-route.tsx
export function loader() {
return { message: 'Hello' };
}
export default function MyRoute() {
const { message } = useLoaderData();
return <div>{message}</div>;
}
扩展翻译
翻译会根据目录名自动以 extPascalCase 形式命名空间化:
src/extensions/my-extension/locales/
├── en-US/translations.json
└── it-IT/translations.json
const {t} = useTranslation('extMyExtension');
t('welcome');
集成标记
在核心代码中标记扩展集成点:
// 单行标记
/** @sfdc-extension-line SFDC_EXT_MY_FEATURE */
import myFeature from '@extensions/my-feature';
// 块标记
{/* @sfdc-extension-block-start SFDC_EXT_MY_FEATURE */}
<Link to="/my-feature">My Feature</Link>
{/* @sfdc-extension-block-end SFDC_EXT_MY_FEATURE */}
适用场景
- 需要向 Storefront Next 店面添加基础代码尚未渲染的模块化功能时。
- 新结构仅被一个店面或垂直领域需要,且不应修改核心代码时。
- 需要通过目标点在店面布局的特定位置插入组件时。
- 需要为扩展添加独立路由和翻译命名空间时。
限制
- 扩展不应重建已存在的内容;重复区块被视为 bug。
- 纯粹视觉变更(颜色、字体、间距)应通过 token/CVA 变更实现,而非扩展。
- 被多个消费者共享的模式应添加到基础组件的槽位/render-prop,而非扩展。
- 永远不要编辑核心代码。
最佳实践
- 自包含——每个扩展应独立。
- 使用目标点——通过 target-config.json 插入 UI,而非编辑核心文件。
- 命名空间翻译——自动命名空间化可防止冲突。
- 顺序很重要——使用 target-config.json 中的 order 控制渲染顺序。
相关技能
- storefront-next:sfnext-i18n - 翻译模式和命名空间用法
- storefront-next:sfnext-routing - 扩展路由如何与路由器集成
- storefront-next:sfnext-components - 扩展中使用的组件模式
参考文档
- Base Audit Reference - 决策门(扩展 vs token/变体 vs 基础槽位)的示例
- Extension Examples Reference - 完整的扩展示例