其他
在 VTEX IO 多 binding…
适用于 VTEX IO 应用在共享域名、按 /us/、/br/ 等路径前缀区分多 binding 的跨境店铺中,需要让链接、资源、跳转、canonical、sitemap 和 API URL 指向当前 binding 的场景。
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
GDI C 35/100
进化评分(GDI)
综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」
内在质量 55/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 39/100 ×0.15
适用场景
在 VTEX IO 多 binding 特定
解决思路
- 判断 binding 形态:单域名多 binding(如 store.com/us/、store.com/br/)时 rootPath 必需,所有生成 URL 必须加当前 binding 的 rootPath 前缀。
- 判断 binding 形态:多域名单 binding(如 store.us、store.com.br)时 rootPath 通常为空或 /,URL 可不加前缀;代码仍要优雅处理 rootPath:非空时使用,为空时跳过。
- 后端(Node):在早期中间件(通常命名为 prepare)中读取请求头 x-vtex-root-path,清洗后存入 ctx.state.rootPath;下游 handler 直接读 ctx.state.rootPath,不再重复解析请求头。
- 后端中间件必须设置 Vary: x-vtex-root-path,让 CDN 按 binding 分别缓存。
- 前端(React):从 vtex.render-runtime 使用 useRuntime().rootPath 获取当前 binding 的路径前缀。
- 始终使用运行时提供的 rootPath,不要硬编码 /us/、/br/ 等区域路径前缀。
- 所有应用生成的 URL——链接、重定向、API endpoint、canonical URL、sitemap 条目——在路径型 binding 店铺中都必须包含 rootPath 前缀。
- 后端正确构造:从 ctx.state 取 rootPath 和 forwardedHost,拼接 https://${forwardedHost}${rootPath}/product/${slug} 作为 canonical,拼接 ${rootPath}/${categoryPath} 作为 sitemap 条目。
- 前端正确构造:在组件中 const { rootPath } = useRuntime(); 并输出 <a href={`${rootPath}/product/${slug}`}>View product</a>。
- 检测错误:查找使用字符串字面量构造的 URL(如 /${slug})而未前置 rootPath,或 navigate() 调用省略 rootPath 前缀。
- 清洗 rootPath 避免双斜杠:当 rootPath === / 时按 空字符串 处理。在 prepare 中:let rootPath = ctx.get('x-vtex-root-path'); if (rootPath && !rootPath.startsWith('/')) { rootPath = `/${rootPath}`; } if (rootPath === '/') { rootPath = ''; } ctx.state.rootPath = rootPath;
- 下游统一使用已清洗的 rootPath:const { rootPath } = ctx.state; const url = `${rootPath}/${path}`;,避免产生 //path。
- 检测错误:URL 拼接写成 rootPath + / + path 而未检查 rootPath === /。
- 在 typings 中声明 State 接口包含 binding、rootPath、forwardedHost、forwardedPath、isCrossBorder、matchingBindings,使所有 handler 有类型化访问。
- prepare 中间件中读取 x-forwarded-host 到 forwardedHost,读取 x-vtex-root-path 到 rootPath,读取 x-forwarded-path 并按 ? 切分取 forwardedPath。
- prepare 中间件中防御畸形 rootPath:若 rootPath 存在且不以 / 开头,则前面补 /。
- prepare 中间件中把 / 归一化为 空字符串,然后写入 ctx.state(保留已有 state),再 await next();。
- prepare 中间件在 await next() 后设置 ctx.vary('x-forwarded-host') 和 ctx.vary('x-vtex-root-path'),确保 CDN 按 host 和 binding 分开缓存。
- 将 prepare 中间件挂到每个路由 middleware chain 的早期位置,保证下游 handler 都能用 ctx.state.rootPath。
- 下游后端 handler 示例:const { rootPath, binding } = ctx.state; const canonicalUrl = `https://${ctx.state.forwardedHost}${rootPath}/${slug}`;。
- 前端封装工具 usePrefixedPath(path):const { rootPath = '' } = useRuntime(); const prefix = rootPath === '/' ? '' : rootPath; return `${prefix}${path.startsWith('/') ? path : `/${path}`}`;。
- 前端 binding-aware API 调用:使用 const { rootPath, binding } = useRuntime();;binding.id 是当前 binding ID,binding.canonicalBaseAddress 形如 store.com/br,rootPath 形如 /br。
- 对 IO 内部调用,平台会自动处理 rootPath;对外部 URL 或自定义重定向,需手动加 rootPath 前缀。
- 避免常见失败:多 binding 中链接未加 rootPath 导致跳错 binding 或 404。
- 避免常见失败:sitemap 生成器漏掉 rootPath,导致搜索引擎索引未加前缀、最终指向默认 binding 的 URL。
- 避免常见失败:rootPath === / 与 /path 拼接产生 //path;必须归一化为空字符串。
- 避免常见失败:硬编码 /us/ 或 /br/,binding 重新配置后会失效。
- 避免常见失败:后端忽略 x-vtex-root-path 请求头,导致多 binding canonical 错误。
- 避免常见失败:响应缺少 Vary: x-vtex-root-path 和 Vary: x-forwarded-host,CDN 可能对不同 binding 返回同一缓存。
- 自检:确认后端有 prepare 中间件读取 x-vtex-root-path 到 ctx.state.rootPath,或前端使用 useRuntime()。
- 自检:确认响应设置 Vary: x-vtex-root-path 和 Vary: x-forwarded-host。
- 自检:确认所有生成 URL(链接、重定向、canonical、sitemap)都加 rootPath 前缀。
- 自检:确认 rootPath === / 归一化为 空字符串,避免双斜杠。
- 自检:确认没有硬编码区域路径前缀(如 /us/、/br/)。
- 自检:确认应用在单 binding 和多 binding 店铺中都工作正常。
适用边界 · 注意事项
- 单 binding 且每个 locale 有独立域名的店铺(无需路径前缀)不要用此技能。
- 一般 IO 后端模式应使用 vtex-io-service-apps,不要用此技能。
- CDN/edge 缓存配置应使用 vtex-io-service-paths-and-cdn,不要用此技能。