关于 b2c-custom-caches
b2c-custom-caches 面向在 Salesforce B2C Commerce 中实现应用级缓存的开发者,介绍 JSON 缓存定义和 Script API 用法,包括加载器填充、键作用域、过期设置及平台限制。
主要功能
- 01在 JSON 文件中定义缓存
- 02通过 Script API 访问缓存
- 03使用加载器填充条目
- 04按站点或目录设置键作用域
- 05配置过期与失效
适用场景
- 01缓存外部 API 响应
- 02避免重复执行高成本计算
- 03复用频繁访问的商品数据
- 04缓存站点级配置
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ salesforcecommercecloud/ b2c-developer-tooling --skill b2c-custom-caches安装后在 Claude Code 中输入/b2c-custom-caches确认已加载。
附带文件evals/trigger-evals.json
详细介绍
B2C 自定义缓存
自定义缓存通过存储计算开销大、检索耗时长或访问频繁的数据来提升代码性能。缓存定义在代码库中的 JSON 文件内,并通过 Script API 访问。
何时使用自定义缓存
| 使用场景 | 示例 |
|---|---|
| 开销大的计算 | 检查是否有任何变体商品在基础商品展示中处于促销状态 |
| 外部系统响应 | 缓存来自外部 API 的门店库存或价格 |
| 配置设置 | 存储来自 JSON 文件或外部来源的配置数据 |
| 频繁访问的数据 | 商品属性、类别数据、站点偏好设置 |
限制
| 限制项 | 值 |
|---|---|
| 每台应用程序服务器的总内存 | 所有自定义缓存共约 20 MB |
| 每个代码版本的最大缓存数 | 100 |
| 最大条目大小 | 128 KB |
| 支持的值类型 | 基本类型、数组、普通对象、null(不包括 undefined) |
| 跨服务器同步 | 无(缓存按应用程序服务器隔离) |
定义自定义缓存
文件结构
my_cartridge/
├── package.json # References caches.json
└── caches.json # Cache definitions
package.json
添加一个 caches 条目,指向缓存定义文件:
{
"name": "my_cartridge",
"caches": "./caches.json"
}
caches.json
定义具有唯一 ID 和可选过期时间的缓存:
{
"caches": [
{
"id": "ProductAttributeCache"
},
{
"id": "ExternalPriceCache",
"expireAfterSeconds": 300
},
{
"id": "SiteConfigCache",
"expireAfterSeconds": 60
}
]
}
| 属性 | 必需 | 说明 |
|---|---|---|
id | 是 | 在代码版本的所有代码库中唯一的 ID |
expireAfterSeconds | 否 | 条目保留的最长秒数 |
使用自定义缓存
Script API 类
| 类 | 说明 |
|---|---|
dw.system.CacheMgr | 访问已定义缓存的入口点 |
dw.system.Cache | 用于存储和检索条目的缓存实例 |
基本用法
var CacheMgr = require('dw/system/CacheMgr');
// Get a defined cache
var cache = CacheMgr.getCache('ProductAttributeCache');
// Get value (returns undefined if not found)
var value = cache.get('myKey');
// Store value directly
cache.put('myKey', { data: 'value' });
// Remove entry
cache.invalidate('myKey');
推荐模式:使用加载器调用 get
使用 get(key, loader),在缓存未命中时自动填充缓存:
var CacheMgr = require('dw/system/CacheMgr');
var Site = require('dw/system/Site');
var cache = CacheMgr.getCache('SiteConfigCache');
// Loader function called only on cache miss
var config = cache.get(Site.current.ID + '_config', function() {
// Expensive operation - only runs if not cached
return loadConfigurationFromFile(Site.current);
});
带作用域的缓存键
在键中包含作用域标识符,以按上下文区分条目:
var CacheMgr = require('dw/system/CacheMgr');
var Site = require('dw/system/Site');
var cache = CacheMgr.getCache('ProductCache');
// Site-scoped key
var siteKey = Site.current.ID + '_' + productID;
var productData = cache.get(siteKey, loadProductData);
// Catalog-scoped key
var catalogKey = 'catalog_' + catalogID + '_' + productID;
var catalogData = cache.get(catalogKey, loadCatalogData);
// Locale-scoped key
var localeKey = request.locale + '_' + contentID;
var content = cache.get(localeKey, loadLocalizedContent);
缓存方法
| 方法 | 说明 |
|---|---|
get(key) | 返回缓存值或 undefined |
get(key, loader) | 返回缓存值,或调用加载器并存储结果 |
put(key, value) | 直接存储值(覆盖现有值) |
invalidate(key) | 移除指定键的条目 |
最佳实践
应该做
- 使用
get(key, loader)模式自动填充缓存 - 在缓存键中包含作用域(站点、目录、区域设置)
- 为时效性数据设置适当的
expireAfterSeconds - 妥善处理缓存未命中(数据可能随时被逐出)
- 使用描述性缓存 ID
不应该做
- 不要在缓存键中包含个人用户数据(键可能会出现在日志中)
- 不要存储 Script API 对象(仅存储基本类型和普通对象)
- 不要依赖缓存条目始终存在(不保证持久性)
- 不要期望缓存跨服务器同步
- 不要存储
undefined值(请改用null)
缓存失效
以下情况会自动清除缓存:
- 活动代码版本中的任何文件发生更改
- 激活了新的代码版本
- 数据复制完成
- 代码复制完成
手动失效仅影响当前应用程序服务器:
var cache = CacheMgr.getCache('MyCache');
// Invalidate single entry (current app server only)
cache.invalidate('myKey');
// Storing undefined has same effect as invalidate
cache.put('myKey', undefined);
常见模式
缓存外部 API 响应
var CacheMgr = require('dw/system/CacheMgr');
var LocalServiceRegistry = require('dw/svc/LocalServiceRegistry');
var priceCache = CacheMgr.getCache('ExternalPriceCache');
function getExternalPrice(productID) {
return priceCache.get('price_' + productID, function() {
var service = LocalServiceRegistry.createService('PriceService', {
createRequest: function(svc, args) {
svc.setRequestMethod('GET');
svc.addParam('productId', args.productID);
return null;
},
parseResponse: function(svc, response) {
return JSON.parse(response.text);
}
});
var result = service.call({ productID: productID });
return result.ok ? result.object : null;
});
}
缓存开销大的计算结果
var CacheMgr = require('dw/system/CacheMgr');
var saleCache = CacheMgr.getCache('ProductSaleCache');
function isProductOnSale(masterProduct) {
return saleCache.get('sale_' + masterProduct.ID, function() {
var variants = masterProduct.variants.iterator();
while (variants.hasNext()) {
var variant = variants.next();
if (isInPromotion(variant)) {
return true;
}
}
return false;
});
}
使用站点作用域的配置缓存
var CacheMgr = require('dw/system/CacheMgr');
var Site = require('dw/system/Site');
var File = require('dw/io/File');
var FileReader = require('dw/io/FileReader');
var configCache = CacheMgr.getCache('SiteConfigCache');
function getSiteConfig() {
var siteID = Site.current.ID;
return configCache.get(siteID + '_config', function() {
var configFile = new File(File.IMPEX + '/src/config/' + siteID + '.json');
if (!configFile.exists()) {
return null;
}
var reader = new FileReader(configFile);
var content = reader.getString();
reader.close();
return JSON.parse(content);
});
}
故障排除
| 问题 | 原因 | 解决方案 |
|---|---|---|
| 找不到缓存异常 | 任意 caches.json 中均未定义缓存 ID | 将缓存定义添加到 caches.json |
| 缓存 ID 重复错误 | 多个代码库使用了相同 ID | 在所有代码库中使用唯一 ID |
| 条目未存储 | 值超过 128 KB 限制 | 减小数据量或缓存部分数据 |
| 条目未存储 | 值包含 Script API 对象 | 仅使用基本类型和普通对象 |
| 缓存未命中异常 | 使用了不同的应用程序服务器,或缓存已清除 | 始终妥善处理缓存未命中 |
请检查自定义错误日志和自定义警告日志中的缓存相关消息。
评论
支持 Markdown