@builder.io/sdk-angular 从零到实战:Builder.io Gen2 Angular SDK 能力全景与版本演进解析
2026/9/16 16:44:29 网站建设 项目流程

@builder.io/sdk-angular 从零到实战:Builder.io Gen2 Angular SDK 能力全景与版本演进解析

【免费下载链接】builderVisual Development for React, Vue, Svelte, Qwik, and more项目地址: https://gitcode.com/GitHub_Trending/bu/builder

导读

本文以@builder.io/sdk-angular(Builder.io Gen2 Angular SDK)的完整变更记录为主线,结合本仓库packages/sdks/output/angular的产物与packages/sdks/src的 Mitosis 源码,系统讲解该 SDK 的内容获取、渲染、个性化、A/B 测试、可视化编辑与多运行时构建能力。读完本文,你将掌握fetchOneEntry/fetchEntries的完整参数体系、Content组件的正确用法、自定义组件注册协议,以及如何为 Angular 17+ 应用接入 Builder 无头可视化开发能力。

SDK 定位与安装

@builder.io/sdk-angular是 Builder 的 Gen2 Angular SDK,与 React、Vue、Svelte、Qwik 等 SDK 一样,由 Mitosis 从同一份跨框架源码编译生成,其 Mitosis 源位于 packages/sdks/src。当前仓库中的产物版本为 0.25.13,见 packages/sdks/output/angular/package.json。

安装与版本约束:

npm install @builder.io/sdk-angular
  • 该 SDK 要求 Angular 版本>=17.3.0,peer 依赖为@angular/common@angular/core(见 package.json)。这一点与 0.21.0 的"🚨 Breaking Change"直接相关:SDK 全面转向 Angular 17+ 的信号(signals)体系。
  • 运行时依赖仅有isolated-vm(用于 Node 端代码块解释执行)与tslibisolated-vm在 0.23.0 从5.0.0升级到6.0.0以支持 Node v24,同时弃用 Node 18 与 Node 20,因此生产环境需使用 Node 22+(0.0.5 时支持 Node v22)或 Node 24。
  • 包通过条件导出(exports)提供node/browser/edge/edge-routine/netlify多种入口,分别指向lib/nodelib/browserlib/edge三个构建产物,对应多 bundle 支持(0.1.0 引入)。

内容获取:fetchOneEntry 与 fetchEntries 完整参数

SDK 的核心数据入口是fetchOneEntry(返回单条内容,内部调用fetchEntries并取limit: 1的首项)与fetchEntries(返回分页数组)。其实现位于 packages/sdks/src/functions/get-content/index.ts,参数类型定义在 packages/sdks/src/functions/get-content/types.ts。

import { fetchOneEntry } from '@builder.io/sdk-angular'; const content = await fetchOneEntry({ apiKey: 'YOUR_API_KEY', model: 'page', userAttributes: { urlPath: '/', device: 'mobile', }, });

GetContentOptions的核心参数:

参数类型默认值 / 说明
modelstring必填,要获取内容的模型名
apiKeystring必填,公开 API Key
limitnumber1(fetchOneEntry 固定为 1)
offsetnumber0,分页偏移
userAttributesRecord<string, any>用户属性,用于定向(如urlPathreturnVisitordevice),随userAttributesJSON 参数发送
queryRecord<string, any>MongoDB 风格查询,如{ data: { myCustomField: { $gt: 20 } } },会被扁平化后写入 URL
localestring自动解析本地化字段(见 0.17.1、0.19.3 的 locale 修复)
enrichboolean是否解析多级引用
enrichOptionsEnrichOptions约束引用解析行为(0.25.13 新增)
fields/omitstring字段白名单/黑名单,omit优先于fields
canTrackbooleantrue,置 false 时禁用 A/B 测试与 Cookie 定向
cacheSecondsnumber缓存秒数,写入 Cache-Control max-age
staleCacheSecondsnumberstale-while-revalidate 的陈旧缓存时长
sort{ [key]: 1 \| -1 }排序,如{ createdDate: 1 }
includeUnpublishedbooleanfalse,是否包含草稿
apiVersion'v3'目前仅支持v3
apiHoststring默认https://cdn.builder.io(0.2.23 新增)
fetch/fetchOptions覆盖全局 fetch 及其 init 参数

URL 的组装逻辑在 generate-content-url.ts 中可查证:缺少apiKey会直接抛出Missing API key;非v3apiVersion会抛出Invalid apiVersionomit的默认值是meta.componentsUsed(对应 0.18.10 的修复);noTraverse参数在limit !== 1时为true以优化列表性能。

enrichOptions:精细控制引用解析(0.25.13)

EnrichOptions(types.ts)允许在开启enrich后约束引用解析的深度与字段:

await fetchOneEntry({ apiKey, model: 'page', enrich: true, enrichOptions: { enrichLevel: 2, // 嵌套引用最多解析 2 层 model: { product: { fields: 'id,name,data.price', // 每模型包含字段 omit: 'data.blocks', // 或省略字段 }, }, }, });

其中enrichLevel决定嵌套引用解析层数,层数越高响应体越大,应尽量取业务所需的最低层数;model按模型名提供fields/omit白黑名单。这些约束不仅影响请求,还会同步告知 Visual Editor 站点使用了哪些约束条件。只有enrich: true时该选项才会被序列化进enrichOptions查询参数(见 generate-content-url.ts)。

错误处理语义(0.17.0)

0.17.0 是一个 Breaking Change:fetchEntriesfetchOneEntry此前会吞掉一切错误并返回null;此后,fetch抛出的任何错误、或 Builder API 返回的任何非成功响应,都会直接向上抛出(见 index.ts 中throw content的实现)。这意味着调用方必须自行 try/catch,并根据null(未命中)与异常(请求失败)区分两种情形。

渲染:Content 组件与标准接入方式

获取到内容后,通过<builder-content>组件渲染。SDK 的 README(packages/sdks/output/angular/README.md)给出了一个完整的独立组件示例:

import { Component } from '@angular/core'; import { Content, fetchOneEntry, type BuilderContent } from '@builder.io/sdk-angular'; @Component({ selector: 'app-catchall', standalone: true, imports: [Content], template: ` @if (content) { <builder-content [model]="model" [content]="content" [apiKey]="apiKey"></builder-content> } @else { <div>404 - Content not found</div> } `, }) export class CatchAllComponent { apiKey = 'YOUR_API_KEY'; model = 'page'; content: BuilderContent | null = null; async ngOnInit() { const urlPath = window.location.pathname || ''; const content = await fetchOneEntry({ apiKey: this.apiKey, model: this.model, userAttributes: { urlPath }, }); if (!content) return; this.content = content; } }

要点:

  • 组件选择器是builder-content:0.2.14 将导出选择器修正为builder-content以兼容 Angular v18;0.2.10 也将content-variants选择器改回content
  • modelcontent是必填 props(0.18.0 Breaking Change),apiKey可额外传入。
  • nonceprop(0.2.1):可为 SDK 内联生成的style/script标签设置nonce属性,便于与 CSP 策略配合。
  • BlocksWrapperProps(0.18.13):允许为单个<blocks>实例覆写全局 props,覆盖时局部 props 完全替换全局 props,除非手动合并(详见 CHANGELOG 中的builderContext.BlocksWrapperProps合并示例)。
  • SSR 注意事项:0.17.4 起,Angular SSR v17+ 应用从 Content 层面跳过 hydration,因为 Angular 不支持对动态创建的元素做 hydration;同时 0.23.1 修复了从 SSR 渲染页面路由跳转时的 hydration 问题。

信号驱动重构:Angular 17+ 的响应式基础(0.21.0)

0.21.0 是 SDK 历史上最重要的重构(🚨 Breaking Change):整个 SDK 迁移到 Angular v17+ 的信号体系(signals、computed、inputs、声明式语句)。CHANGELOG 明示了两个收益:

  • 重算时机收窄:只有当依赖的信号更新时才重新计算,而不是每个变更检测周期都重算;
  • 渲染范围收窄:带子组件的组件不再因任何变更而整棵重渲染,消除了 Visual Editor 中的卡顿交互。

从 0.25.7 的修复可以进一步印证这一内部机制:props.content更新钩子被编译为 Angulareffect(),它跟踪函数体内实际读取到的所有信号而非声明的依赖列表,因此任何无关的 context 更新都可能重新触发合并逻辑,导致编辑器里的改动被页面初次加载的props.content覆盖。修复方式是为合并加上prevContent守卫,与相邻的props.dataprops.locale钩子采用同一模式。

配套的版本门控在 0.25.4:被弃用的allowSignalWriteseffect 选项不再被无条件丢弃,而是按运行时 Angular 版本(VERSION.major < 19)决定是否传递,从而在 Angular 19+ 上消除弃用告警,同时保持对低版本的向后兼容。

自定义组件注册:registerComponent 与 ComponentInfo

SDK 允许注册自定义组件供可视化编辑器使用,注册信息通过builder.registerComponent消息序列化后发送给编辑器(见 register-component.ts)。类型定义在 packages/sdks/src/types/components.ts,其中包括:

  • name:唯一组件名;可以用同名注册覆盖内置组件(如Text);
  • inputs:输入 schema(含typerequiredautoFocusbubbledefaultValue等字段);
  • group?: string(0.25.10 新增):把自定义组件归入编辑器插入菜单中自己的折叠分组,相同group的组件聚合在一起,未设置或为空时回退到默认的 "Custom Components" 分组;
  • canHaveChildren/noWrap/fragment:子节点与包裹元素行为;
  • models:限定组件可用的模型列表(0.2.3 修复);
  • requiredPermissions:按用户权限限制组件可见性;
  • override:覆盖内置组件时跳过默认特殊行为(如 Image 的宽高比编辑器、Columns 的列编辑器);
  • hooks:自定义生命周期钩子;
  • meta(0.17.1 新增):组件元信息。

shouldReceiveBuilderProps:精确控制 Builder props 注入

注册组件的shouldReceiveBuilderProps配置决定 SDK 是否向组件注入builderBlockbuilderContextbuilderComponentsbuilderLinkComponent四个 Builder props。

  • 0.1.0 引入时默认值:builderBlock: truebuilderContext: true、其余false,并给出按需覆写的示例(如只保留builderBlockbuilderComponents);
  • 0.2.0 将其改为全部默认false——默认不再注入任何 Builder props,只有显式打开对应开关才注入。

仓库中的内置组件是很好的参照:accordion/component-info.ts、columns/component-info.ts、form/component-info.ts、symbol/component-info.ts 四者都全量开启;button/component-info.ts 只开启builderLinkComponent;image/component-info.ts 只开启builderBlock

输入回调与序列化

  • 0.2.19 为自定义组件输入的onChange增加了第二个参数previousOptions,回调在旧 options 状态下触发前保留快照,且支持异步函数(0.17.1);
  • 0.2.9 / 0.2.5 保证注册信息与插件中的函数(如字段上的showIf函数)可以被正确序列化;0.25.11 进一步让showIf回调能接收父级参数并通过context.locale读取编辑器当前 locale;
  • 0.25.10 同时修复了 Image 组件在 alt 文本为空时渲染显式空alt属性,避免无障碍语义丢失。

个性化与 A/B 测试

setClientUserAttributes:写入用户属性 Cookie

setClientUserAttributes自 0.17.7 导出,用于设置 Builder 的用户属性 Cookie,该 Cookie 被 Personalization Containers(个性化容器)用来决定渲染哪个变体:

import { setClientUserAttributes } from '@builder.io/sdk-angular'; setClientUserAttributes({ device: 'tablet', });

其底层实现在 packages/sdks/src/helpers/user-attributes.ts:调用userAttributesService.setUserAttributes,把新属性与已有属性合并后写入名为builder.userAttributes的 Cookie,并通知所有订阅者;在非浏览器环境(SSR)下直接跳过写入。注意canTrack: false时不会写入 Cookie,0.0.6 还修复过 Symbols 中canTrack=false不被尊重的问题。

A/B 测试的脚本注入策略

A/B 测试(0.18.3 引入支持)相关内联脚本的注入经历了一个"引入 → 去重 → 回退 → 再修复"的演进:

  • 0.25.2 与 0.25.3:先移除 DOM 中重复插入的 A/B 测试脚本,随即因引发 hydration 回归而回退;
  • 0.25.5:window.builderIoAbTest/window.builderIoRenderContent初始化脚本改为仅在 Content 实际渲染 A/B 变体时才注入,且定义为幂等、在 hydration 目标上自移除,从而在不做客户端 DOM 变更的前提下避免重复注入;
  • 0.25.9:同样的策略推广到个性化脚本——window.builderIoPersonalization/window.filterWithCustomTargeting/window.updateVisibilityStylesScript此前每个顶层Content都会注入一次(无论是否存在 Variant Container),现在只由实际包含个性化块的Content注入,定义同样幂等。

另外,fetchEntries/fetchOneEntry在浏览器端会通过handleABTesting在客户端导航场景直接处理 A/B 测试(见 get-content/index.ts);0.18.2 修复了/track调用在默认与变体场景下重复上报的校验逻辑;0.24.1 修复了trackConversion方法。0.25.12 修复了 Builder Studio 定向请求中布尔型用户属性的处理。

可视化编辑:subscribeToEditor 与编辑器通信

可视化编辑依赖 SDK 与编辑器 iframe 之间的 postMessage 通信。0.18.0 对subscribeToEditor做了破坏性改造:参数从位置参数改为具名参数对象,且apiKey变为必填:

// 旧写法(已废弃) subscribeToEditor('page', () => { ... }, { trustedHosts: ['...'] }); // 新写法 subscribeToEditor({ apiKey: '...', model: '...', trustedHosts: ['...'], callback: () => { ... }, });

编辑器消息的接收端在 packages/sdks/src/helpers/subscribe-to-editor.ts:每次收到 MessageEvent 都会先经过isFromTrustedHost(trustedHosts, event)校验,然后按消息类型分发到builder.configureSdkbuilder.triggerAnimationbuilder.resetStatebuilder.contentUpdate等回调。0.25.6 加强了来源校验——改用精确的可信主机名比对,并拒绝格式非法或非 HTTP(S) 的 origin(0.0.8 起就要求先确认e.origin是合法 URL)。

可视化编辑相关的历史修复还包括:

  • 0.18.1:编辑器 iframe 中修改输入值能即时触发变更;
  • 0.18.4:Custom Code 块的代码修改实时反映、修复nativeElement找不到的问题(0.17.3 起支持嵌入 iframe);
  • 0.18.6 / 0.18.7 / 0.18.9:修复可视化编辑时新子块被添加到顶部的问题(Section 等使用 children 渲染的组件),0.18.7 引入ngAfterContentChecked钩子并补充详尽注释;
  • 0.25.7:修复编辑器改动被初次渲染内容覆盖的回归(即前文effect()跟踪问题);
  • 0.18.12:Symbol 条目在编辑器中变化时加载正确内容;
  • 0.17.2:支持在 Builder Visual Editor 的 Studio 标签中预览内容。

图像与多媒体块的能力演进

Image / Video / RawImg 块的优化贯穿整个版本历史,是性能与功能并重的典型模块:

  • 响应式图片:0.19.0 为 RawImg 组件添加srcset,并给 Video 组件接入 Intersection Observer 实现视口懒加载;0.19.1 给 RawImg 加loading="lazy";0.25.8 在 Gen2 SDK 中暴露 Image 的sizes字段并修复响应式源的选择逻辑;
  • 加载策略:0.0.7 为 Image 块增加highPriority选项实现 eager 加载;0.17.9 为 video 元素增加懒加载;0.17.6 移除 Video 块的 z-index(避免遮挡子元素);
  • 文件类型:0.0.9 支持 Image 块上传webp,0.17.1 扩展了 Image/Video 块允许的文件类型;0.0.9 同时移除了 Embed 块逻辑中硬编码的iframelyAPI key;0.2.3 修复 SVG 图片冗余srcset;0.18.8 为图片增加title选项;
  • 表单块:0.0.10 支持 TextArea 块并修复 Select/TextArea 的required选项;0.17.5 修复 Form 块重复渲染 children;0.18.15 修复表单提交错误处理;0.20.1 修复表单提交应使用 radio 的值而非 name。

运行时与多环境构建:node / browser / edge

SDK 针对不同运行环境产出独立 bundle(0.1.0 引入多 bundle 支持),构建脚本见 packages/sdks/output/angular/package.json:build依次执行build:nodebuild:browserbuild:edge,产物输出到lib/下的node/browser/edge三个目录。

  • Node 端代码执行:依赖isolated-vm沙箱解释执行 JS 代码块(见 packages/sdks/src/functions/evaluate/node-runtime)。0.2.17 修复了 arm64 机器运行 Node 20 时禁用initializeNodeRuntime()的问题;0.24.0 消除长时间运行 Node.js 进程中的内存泄漏;0.22.3 保证只有导入 edge build 时才使用 edge runtime。
  • SSR 支持:0.1.0 为 A/B 测试与 Symbols 提供 SSR;0.2.2 将onInit转换为服务端与客户端都执行的ngOnInit,而onMount/onUpdate只在浏览器执行(带浏览器判断的ngOnInit/ngOnChanges);0.2.24 修复 Builder children 块未被 SSR 的问题。
  • 调试:0.2.26 支持在process.env.DEBUG=true时记录 SDK 命中的每个 API URL。

版本演进路线图

从 0.0.1 的 alpha 至今,SDK 的演进可归纳为几个关键节点:

版本里程碑
0.0.1 – 0.0.10alpha 起步:Angular 16.2+ 支持、多 bundle、TextArea/WebP 等基础能力
0.1.0 – 0.2.0shouldReceiveBuilderProps引入并默认收敛为全关闭;SSR A/B 测试与 Symbols
0.17.0 – 0.18.0获取 API 抛错语义、subscribeToEditor具名参数化、model/content必填、A/B 测试支持
0.21.0全面信号化重构,最低 Angular 17.3.0
0.22.x – 0.25.x脚本注入去重与幂等、Visual Editor 修复、group分组、enrichOptions

对照 CHANGELOG(packages/sdks/output/angular/CHANGELOG.md)可以看到,每一次 Patch 都与具体的源码行为一一对应,这也是将 CHANGELOG 作为 SDK 行为说明书使用的价值所在:它记录了每个参数的引入时机(如apiHost在 0.2.23、nonce在 0.2.1)、每个 Breaking Change 的迁移方式,以及大量可视化编辑、SSR、个性化场景下的边界修复。升级 SDK 前,对照该文件逐条排查影响面,是避免回归的最直接手段。

实践建议总结

  1. 内容获取:优先使用fetchOneEntry+userAttributes(至少包含urlPath)完成首屏渲染;列表场景使用fetchEntries配合limit/offset/query/sort;需要引用解析时开启enrich并用enrichOptions收敛体积。
  2. 错误处理:0.17.0 之后fetchOneEntry可能抛异常,务必 try/catch,并用null与异常区分"无内容"与"请求失败"。
  3. 组件注册:自定义组件默认不再收到任何 Builder props,按需开启shouldReceiveBuilderProps;用group归组插入菜单项;用models限制可用模型。
  4. 个性化与 A/B:通过setClientUserAttributes在客户端更新定向属性;理解脚本注入的幂等策略,避免页面多Content时的重复脚本问题。
  5. 运行时选型:Node 24 / 22 环境使用 node build,边缘函数场景按条件导入 edge build;Angular 应用需确保版本>=17.3.0

【免费下载链接】builderVisual Development for React, Vue, Svelte, Qwik, and more项目地址: https://gitcode.com/GitHub_Trending/bu/builder

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询