关于 faststore-overrides
为 FastStore 开发者提供组件和区块覆盖指导,使用官方 Override API 调整原生组件的属性、行为或实现。适用于主题和设计令牌无法满足定制需求的场景。
主要功能
- 01使用 getOverriddenSection() 定义覆盖
- 02替换原生组件或调整其属性
- 03按约定路径和名称组织覆盖文件
- 04遵循可覆盖组件与公开 API 限制
适用场景
- 01替换商品详情区块中的原生组件
- 02为原生区块注入自定义逻辑
- 03修改组件属性以适配店铺需求
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ vtex/ skills --skill faststore-overrides安装后在 Claude Code 中输入/faststore-overrides确认已加载。
详细介绍
FastStore 区块与组件覆盖
适用场景
在以下情况下使用此技能:
- 需要自定义 FastStore 店铺组件的行为或外观,而主题设置和设计令牌无法实现所需效果。
- 需要用自定义实现完全替换原生组件。
- 需要在区块内注入自定义逻辑,或修改原生组件的属性。
- 正在处理
src/components/overrides/中的文件。
以下情况不要使用此技能:
- 仅进行视觉调整(颜色、字体、间距)——请改用
faststore-theming技能和设计令牌。 - 为购物车、会话或搜索构建自定义状态管理——请改用
faststore-state-management技能。 - 扩展 GraphQL 数据层——请改用
faststore-data-fetching技能。
决策规则
- 仅当主题设置无法实现所需更改时才使用覆盖(例如,替换组件、添加逻辑、更改行为)。
- 要完全替换原生组件时,使用
components映射,并设置{ Component: CustomComponent }。 - 只需修改原生组件属性而不替换组件时,使用
components映射,并设置{ props: { ... } }。 - 在更改行为的同时进行包装器级样式设置时,使用
getOverriddenSection()的className选项。 - 纯粹的视觉更改优先使用设计令牌进行主题设置——覆盖的影响范围更大,耦合也更紧密。
- 仅覆盖 FastStore 原生区块文档中列为可覆盖的组件。未记录的组件名称会被静默忽略。
- 以
__experimental为前缀的组件可以覆盖,但无法访问其属性,且这些属性可能会在不另行通知的情况下更改。
硬性约束
约束:使用覆盖 API,绝不修改 FastStore 核心
自定义区块时,必须使用 @faststore/core 中的 getOverriddenSection()。不得直接修改 node_modules/@faststore/ 中的文件,也不得导入内部源文件。
原因
修改 node_modules 是临时性的(运行 npm install 后更改会丢失),而从 @faststore/core/src/ 等内部路径导入会与实现细节紧密耦合,任何 FastStore 更新都可能导致问题。
检测
如果看到从 @faststore/core/src/(内部源文件路径)导入内容 → 立即停止。这些是私有实现细节。只能从公共 API 导入:@faststore/core 和 @faststore/core/experimental。如果看到直接编辑 node_modules/@faststore/ 中的文件 → 立即停止,改用覆盖系统。
正确
// src/components/overrides/ProductDetails.tsx
import { getOverriddenSection } from '@faststore/core'
import { ProductDetailsSection } from '@faststore/core'
import CustomProductTitle from '../CustomProductTitle'
const OverriddenProductDetails = getOverriddenSection({
Section: ProductDetailsSection,
components: {
ProductTitle: { Component: CustomProductTitle },
},
})
export default OverriddenProductDetails
错误
// WRONG: Importing from internal source paths
import { ProductDetails } from '@faststore/core/src/components/sections/ProductDetails'
// This path is an implementation detail that can change without notice.
// It bypasses the public API and will break on FastStore updates.
// WRONG: Modifying node_modules directly
// Editing node_modules/@faststore/core/dist/components/ProductDetails.js
// Changes are lost on every npm install and cannot be version-controlled.
约束:覆盖文件必须位于 src/components/overrides/
必须将覆盖文件放在 src/components/overrides/ 目录中,并根据要覆盖的区块命名(例如 ProductDetails.tsx)。
原因
FastStore 的构建系统会扫描 src/components/overrides/,以发现并应用区块覆盖。文件放在其他位置将无法被检测到,覆盖也会静默失败——原生区块仍会正常渲染,且不会显示错误信息。
检测
如果在 src/components/overrides/ 之外的文件中看到与覆盖有关的代码(调用 getOverriddenSection)→ 提醒用户该覆盖不会生效。检查文件名是否与 FastStore 区块列表中的有效原生区块名称匹配。
正确
// src/components/overrides/Alert.tsx
// File is in the correct directory and named after the Alert section
import { getOverriddenSection } from '@faststore/core'
import { AlertSection } from '@faststore/core'
import CustomIcon from '../CustomIcon'
const OverriddenAlert = getOverriddenSection({
Section: AlertSection,
components: {
Icon: { Component: CustomIcon },
},
})
export default OverriddenAlert
错误
// src/components/MyCustomAlert.tsx
// WRONG: File is NOT in src/components/overrides/
// FastStore will NOT discover this override.
// The native Alert section will render unchanged.
import { getOverriddenSection } from '@faststore/core'
import { AlertSection } from '@faststore/core'
const OverriddenAlert = getOverriddenSection({
Section: AlertSection,
components: {
Icon: { Component: CustomIcon },
},
})
export default OverriddenAlert
约束:仅覆盖文档中列出的可覆盖组件
必须仅覆盖 FastStore 原生区块文档中列为可覆盖的组件。以 __experimental 开头的组件可以覆盖,但无法访问其 props。
为何这很重要
尝试覆盖未列为可覆盖的组件会静默失败。覆盖配置将被忽略,并渲染原生组件。标记为 __experimental 的组件具有不稳定的 props 接口,可能会在未提前通知的情况下发生变化。
检测
如果你在 components 覆盖映射中看到某个组件名称,但它未出现在该区块的 FastStore 可覆盖组件列表中 → 警告该覆盖可能无效。如果组件名称以 __experimental 开头 → 警告其 props 无法访问且不稳定。
正确
// src/components/overrides/ProductDetails.tsx
// ProductTitle is a documented overridable component of ProductDetails section
import { getOverriddenSection } from '@faststore/core'
import { ProductDetailsSection } from '@faststore/core'
const OverriddenProductDetails = getOverriddenSection({
Section: ProductDetailsSection,
components: {
ProductTitle: {
props: {
refNumber: true,
showDiscountBadge: false,
},
},
},
})
export default OverriddenProductDetails
错误
// src/components/overrides/ProductDetails.tsx
// "InternalPriceCalculator" is NOT a documented overridable component
import { getOverriddenSection } from '@faststore/core'
import { ProductDetailsSection } from '@faststore/core'
const OverriddenProductDetails = getOverriddenSection({
Section: ProductDetailsSection,
components: {
// This component name does not exist in the overridable list.
// The override will be silently ignored.
InternalPriceCalculator: { Component: MyPriceCalculator },
},
})
export default OverriddenProductDetails
推荐模式
推荐的文件布局:
src/
├── components/
│ ├── overrides/
│ │ ├── ProductDetails.tsx ← override file (named after section)
│ │ ├── Alert.tsx
│ │ └── simple-alert.module.scss
│ ├── CustomBuyButton.tsx ← custom component
│ └── BoldIcon.tsx
最小覆盖 — 替换组件:
// src/components/overrides/ProductDetails.tsx
import { getOverriddenSection } from '@faststore/core'
import { ProductDetailsSection } from '@faststore/core'
import CustomBuyButton from '../CustomBuyButton'
const OverriddenProductDetails = getOverriddenSection({
Section: ProductDetailsSection,
components: {
BuyButton: { Component: CustomBuyButton },
},
})
export default OverriddenProductDetails
覆盖 props 而不替换组件:
// src/components/overrides/ProductDetails.tsx
import { getOverriddenSection } from '@faststore/core'
import { ProductDetailsSection } from '@faststore/core'
const OverriddenProductDetails = getOverriddenSection({
Section: ProductDetailsSection,
components: {
BuyButton: {
props: {
size: 'small',
iconPosition: 'left',
},
},
},
})
export default OverriddenProductDetails
使用自定义样式进行覆盖:
// src/components/overrides/Alert.tsx
import { getOverriddenSection } from '@faststore/core'
import { AlertSection } from '@faststore/core'
import styles from './simple-alert.module.scss'
import BoldIcon from '../BoldIcon'
const OverriddenAlert = getOverriddenSection({
Section: AlertSection,
className: styles.simpleAlert,
components: {
Icon: { Component: BoldIcon },
},
})
export default OverriddenAlert
常见失败原因
- 对于覆盖系统支持的更改,猴子补丁
node_modules/@faststore/或使用patch-package。安装时更改会丢失,并增加维护负担。 - 使用 CSS
!important强制实现视觉更改,而不是针对行为更改使用覆盖 API,或针对视觉更改使用设计令牌。 - 在原生区块外创建包装组件,而不是使用
getOverriddenSection()。包装组件会绕过 CMS 集成、分析跟踪和区块发现。 - 将覆盖文件放在
src/components/overrides/之外 — 这些文件会被静默忽略。 - 覆盖 FastStore 可覆盖组件文档中未列出的组件名称 — 该覆盖会被静默忽略。
审查清单
- 覆盖文件是否位于
src/components/overrides/中,并以目标区块命名? - 文件是否使用了来自
@faststore/core的getOverriddenSection()? - 所有被覆盖的组件名称是否都在该区块的可覆盖组件文档中列出?
- 导入是否仅来自
@faststore/core或@faststore/core/experimental(而非内部源代码路径)? - 这项更改是否可以通过设计令牌实现,而无需覆盖?
- 覆盖是否以 default 形式导出?
参考
- 覆盖概览 — FastStore 覆盖系统简介及其适用场景
- getOverriddenSection 函数 — 核心覆盖函数的 API 参考
- 覆盖原生组件和 props — 覆盖组件 props 的分步指南
- 覆盖原生组件 — 完全替换原生组件的指南
- 原生区块和可覆盖组件列表 — 各区块可覆盖组件的完整参考
- 创建新区块 — 覆盖无法满足需求时创建自定义区块的指南
- 覆盖故障排除 — 覆盖不起作用时的常见问题和解决方案
faststore-theming— 用于无需覆盖即可进行视觉自定义的相关技能