ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

Metabase 自定义可视化 SDK 演进:`@metabase/custom-viz` 2.0 破坏性变更与迁移实战

Metabase 自定义可视化 SDK 演进:`@metabase/custom-viz` 2.0 破坏性变更与迁移实战 Metabase 自定义可视化 SDK 演进metabase/custom-viz2.0 破坏性变更与迁移实战【免费下载链接】metabaseThe easy-to-use open source Business Intelligence and Embedded Analytics tool that lets everyone work with data :bar_chart:项目地址: https://gitcode.com/GitHub_Trending/me/metabasemetabase/custom-viz是 Metabase 官方提供的自定义可视化Custom Visualizations开发工具包集类型化 API 与命令行工具于一体帮助开发者用 React 编写自定义图表插件并打包上传到 Metabase。本文以该包 CHANGELOG.md 为主线系统梳理 2.0.0 的破坏性变更、新增能力与迁移步骤并结合仓库源码揭示底层实现原理帮助你安全升级插件、理解设置存储与版本兼容机制。一、认识metabase/custom-vizmetabase/custom-viz是一个独立发布的 npm 包位于仓库的 enterprise/frontend/src/custom-viz 目录。它的定位正如 README.md 所写API and CLI for creating custom visualizations for Metabase——既提供类型定义defineConfig、CreateCustomVisualization等也提供两个 CLI 子命令init脚手架一个全新的自定义可视化项目pack把构建产物打包成可直接上传的.tgz。从 package.json 可以看到npm 包暴露的二进制名为metabase-custom-vizbin: { metabase-custom-viz: dist/cli.js }CLI 基于 commander 实现。其 CHANGELOG 覆盖了metabase/custom-viz包本身的 API 与 CLI 变化而 Metabase 如何托管自定义可视化插件则记录在 Metabase 总 changelog 中——两者的边界划分清晰升级插件时应同时关注。快速上手三步走详见 README.md# 1. 脚手架一个新可视化项目 npx metabase/custom-viz init my-viz # 2. 安装依赖并进入开发模式watch 模式改动即重建 cd my-viz npm install npm run dev # 3. 构建生产产物输出到 dist/上传至 Metabase npm run build二、2.0.0 破坏性变更全景2.0.0 是metabase/custom-viz自 1.0.0 稳定版之后的一次大版本升级包含多项 API 与存储层面的破坏性变更。逐条理解它们才能顺利完成插件迁移。2.1column与column_settings成为保留设置 idMetabase 为每个自定义可视化注入了内置的逐列格式化per-column formatting弹层为此column和column_settings被设为保留设置 id见 [#78128] 对应的变更记录。如果你的插件曾在这两个 id 下声明过自己的设置必须重命名。类型层面已经对此施加了强制约束在 types/viz-settings.ts 中ReservedVisualizationSettingId被定义为column | column_settings而BaseVisualizationSettings通过映射类型让这两个 key 的类型退化为一段提示文案——一旦你的Settings类型出现这两个 keyTypeScript 会直接报类型错误export type ReservedVisualizationSettingId column | column_settings; export type BaseVisualizationSettings Recordstring, unknown { [K in ReservedVisualizationSettingId]?: ${K} is a reserved setting id added by Metabase; remove it from your Settings type; };2.2 设置存储迁移到custom:plugin name:setting id命名空间这是 2.0.0 最核心的存储层变更对应 [#81181]插件设置不再直接写在问题question的visualization_settings顶层而是统一收纳到custom:plugin name:setting id前缀的 key 下。这样做的直接收益是——插件永远无法覆盖 Metabase 自身的设置如card.title、click_behavior等。对插件作者而言日常写法几乎没有变化你在settings、onChangeSettings、readDependencies、writeDependencies、eraseDependencies中依然使用自己的短 id如threshold前缀翻译由 Metabase 完成并保证只作用于插件自己的设置。后端对这套命名空间机制有配套约束在 manifest.clj 中插件标识符identifier不允许包含:因为:正是custom:identifier:setting id的分隔符——一旦标识符含冒号就可能读取到其他插件的设置。API 层同样在注册时校验这一点见 api.clj 的identifier-error检查注册接口会直接返回 400。2.3onChangeSettings与依赖列表类型收窄配合命名空间化onChangeSettings以及readDependencies/writeDependencies/eraseDependencies的类型被收窄为只接受插件自己的设置 id。这意味着往onChangeSettings里写card.title、click_behavior等 Metabase 设置将不再生效类型层面向这些字段传入 Metabase 设置 key 会触发编译错误。仓库中的示例插件fixtures/example_custom_viz_plugin/src/index.tsx刻意保留了这样一段反例注释其RenameQuestionWidget试图在onChangeSettings中写入card.title代码上用ts-expect-error明确标记——因为 SDK 类型有意拒绝了内部 Metabase 设置 id。2.4 旧版本设置自动迁移兼容性方面2.0.0 提供了自动迁移旧版本插件保存的设置会以新 keycustom:plugin name:setting id自动采纳插件用户无需手工迁移问题卡片。但需要注意一个遗留点旧版本插件写入的 Metabase 设置包括click_behavior会保留在存储中并继续生效直到被手动移除。因此升级后应重点检查现有自定义可视化卡片上的点击行为click behavior配置确认其仍然符合预期必要时手动清理。2.5ClickObject不再泛型、不再携带settings字段2.0.0 中ClickObject被简化为非泛型类型且删除了settings字段。现在 Metabase 会在每次点击时自行把可视化当前设置附加到点击对象上并忽略插件在settings字段传入的任何内容——这么做的目的是防止插件通过点击对象重定向仪表盘点击行为click behavior。当前仓库中的ClickObject定义types/viz.ts只包含value、column、dimensions、event、element、origin、data等与数据点定位、弹层定位相关的字段确认不再有settings。若旧插件代码中读取clickObject.settings升级后需移除旧版本保存的click_behavior在手动移除前依然生效。2.6 顶层colorSchemeprop 移入renderingContext原先作为可视化组件顶层 prop 的colorScheme被移入新增的renderingContextprop对应 [#78429]。迁移方式// 旧写法已废弃 props.colorScheme // 新写法 props.renderingContext.colorScheme2.7 可视化定义的id字段移除可视化定义defineConfig传入的对象中的id字段被移除。它从未被真正读取过——Metabase 始终通过metabase-plugin.json中的name来标识一个可视化。直接删除defineConfig调用中的id即可。2.8 模块级measureText系列导出移除measureText、measureTextWidth、measureTextHeight三个模块级导出被删除。它们原本只是恒返回零尺寸的桩实现stub没有实际测量能力。需要真实文本测量时请使用新的renderingContextprop 上的measureText详见下文 3.2 节。三、2.0.0 新增能力3.1 逐列格式化column设置函数visualization_settings中新增了一个column函数用于解析某一列的实际生效的格式化设置。合并顺序为后者覆盖前者实例级默认值instance-wide defaults列的元数据设置columns metadata settings卡片级列格式化弹层中配置的设置card-level settings。把column(column)的返回值传给formatValue即可让图表数值按用户在界面上的配置渲染。这一设计的类型说明见 types/viz-settings.ts 中CommonVisualizationSettings的column字段注释该文件还注释说明column_settings按 key 索引的原始对象被有意排除在公开类型之外因为 SDK 不暴露计算其中 key 的 API消费者应改用column()。值得留意的是formatValue在运行时并非纯前端实现查看 format.ts 可以看到它委托给window.__METABASE_VIZ_API__.formatValue——该 API 由 Metabase 在插件执行前注入若在 Metabase 实例之外调用会直接抛错。这也解释了为何格式化能力必须与宿主host深度绑定。3.2 新的renderingContextproprenderingContext是 2.0.0 引入的宿主渲染上下文提供四类渲染辅助能力类型定义见 types/viz.ts 的RenderingContext接口成员签名作用getColor(colorName: string) string将 Metabase 颜色名解析为当前主题下的实际颜色值measureText(text, style) { width, height }按 Metabase 的渲染方式测量文本style.family缺省时使用实例字体单次测量同时返回宽高fontFamilystring暴露实例字体便于你为自己的 DOM 标记设置字体colorSchemelight \| dark告知当前是浅色还是深色渲染模式文本测量的类型定义types/measure-text.ts为TextMeasurer (text: string, style: FontStyle) TextSize其中FontStyle含size、family、weight。相比被移除的桩函数这是唯一能获得真实测量结果的途径。3.3 新增pack命令metabase/custom-viz pack将构建产物打包成可直接上传的.tgz。它的意义在于脚手架项目无需再自带打包脚本默认模板的build脚本已改为vite build metabase-custom-viz pack见 templates/package.json打包逻辑与体积限制的修复随包升级自动生效支持--dir参数指定其他目录下的项目。从 cli.ts 看pack命令通过--dir dir选项默认.解析项目目录随后调用packPlugin成功时输出Packed outPath (size KiB)。3.4 打包时自动盖章sdk.versionpack会把当前metabase/custom-viz的精确版本写入打包后的 manifest 的sdk.version字段并且不修改你的源metabase-plugin.json。这一印章与后端的版本兼容检测联动。在 pack.ts 中packPlugin读取 manifest 后构造stampedManifest注入sdk: { ...manifest.sdk, version: SDK_VERSION }再写入 tar 包。而后端 manifest.clj 定义了tested-sdk-version-range当前为2.0即本仓库 Metabase 实际测试过的 SDK 版本范围sdk-version-tested?会去掉预发布与构建元数据让 canary 版本也能匹配对应正式版后做 semver 范围判断。关键行为是插件版本落在测试范围之外或超出其metabase.version范围时Metabase 不会拒绝上传或运行——插件照常加载执行只是在管理后台页面显示一条警告。这也呼应了 README 中soft warning的设计属于非阻断式的兼容提示。3.5getName变为可选getName现在可以省略其返回值是界面中显示的可视化名称省略时使用metabase-plugin.json中的name保留时可用于展示本地化或人类友好的名称。在 types/viz.ts 中getName?: () string的注释明确写着Defaults to the plugin name from the manifest。脚手架模板templates/index.tsx给出的示例为getName: () __CUSTOM_VIZ_DISPLAY_NAME__。3.6checkRenderable变为可选checkRenderable同样变为可选当你的可视化能渲染任意数据时直接省略需要限制时在其中抛错以向用户展示自定义错误信息没有checkRenderable的可视化永远被视为可渲染。类型定义见 types/viz.tscheckRenderable?: (series, settings) void | never注释明确Metabase shows the thrown message to the user。模板与示例插件都演示了其典型用法——例如校验 series 数量、列数、行数及数值类型见 templates/index.tsx 与 fixtures/example_custom_viz_plugin/src/index.tsx。3.7 Bug FixesFormatValueOptions[date_style]现在接受null与 Metabase 实际传入的值保持一致对应 [#70306]。相关类型位于 types/format.ts 及 types/date-time.ts。四、迁移到pack命令如果你在 2.0.0 之前脚手架过项目项目根目录会自带一份pack.mjs。迁移到内置 CLI 只需四步将metabase/custom-viz升级到 2.0.0 或更新版本修改package.json中的build脚本为vite build metabase-custom-viz pack删除项目根目录的pack.mjs从devDependencies中移除tar-stream和types/tar-stream然后重新安装依赖。最后运行npm run build确认项目根目录仍能产出name-version.tgz即可。当前模板项目的 package.json 正是采用上述build脚本形式可作为迁移后的参考基线。关于pack的产物还可以结合 pack.ts 理解其行为细节打包布局为 manifest 在根、dist/index.js与dist/assets/*资源文件与后端期望的目录结构一致要求项目根存在metabase-plugin.json含非空name和package.json含非空version否则报错支持将 manifest 中icon与assets声明的资源一并打进dist/assets/缺失会报错内置体积上限压缩后MAX_COMPRESSED_BYTES 5 MiB未压缩MAX_UNCOMPRESSED_BYTES 25 MiB超限直接拒绝打包。五、1.x 版本演进回顾2.0.0 之前metabase/custom-viz经历了从 1.0.0 初始稳定版到 1.0.5 的若干迭代理解这些历史变更有助于排查旧插件行为1.0.52026-07-23脚手架项目的.gitignore现在忽略dist/与*.tgz对应 [#78355]避免打包产物误提交更新了脚手架项目自带的 README对应 [#75332] 与 [#78355]。1.0.42026-06-03自定义 React 组件可作为设置 widget设置定义中的widget除了内置 widget 名称外现在接受React.ComponentTypegetProps被类型化为返回组件自身的 props排除设置渲染器注入的基础 props对应 [#73941]。在 types/viz-settings.ts 中可以看到内置 widget 全集input、number、radio、select、toggle、segmentedControl、field、fields、color、multiselect。自定义组件 widget 在离开插件沙箱前会被内部改写成WidgetMount宿主永远不会拿到裸的 React 组件引用——这与插件的 near-membrane 隔离模型一致。1.0.32026-06-02安全修复脚手架项目中的 Vite 从 8.0.0 升级到 8.0.16以纳入上游安全修复对应 [#75053]。当前模板的 package.json 锁定vite: 8.0.16即这一修复的落地状态。1.0.22026-06-01破坏性变更从可视化组件 propsCreateCustomVisualizationProps中移除了getAssetUrl——内联图片等静态资源请直接打包进插件代码如 base64 字符串对应 [#74960]。1.0.12026-05-15破坏性变更设置定义中的section?: string替换为getSection?: () string使分区标签可以在调用时本地化对应 [#74077]。当前类型types/viz-settings.ts中正是getSection形式。1.0.02026-05-08初始稳定版。六、从源码看 2.0.0 的底层支撑CHANGELOG 之外仓库源码为 2.0.0 的几项关键设计提供了完整的实现佐证。6.1 设置命名空间与渲染沙箱设置命名空间化的核心动机是把Metabase 自己的设置与插件的设置彻底隔离。前端类型层面通过ReservedVisualizationSettingId与BaseVisualizationSettings拒绝保留 id见 2.1 节后端则通过manifest.clj的identifier-error拒绝含:的插件标识符见 2.2 节前后端双保险。插件渲染的沙箱化同样体现在 define-config.tsxdefineConfig生成的mount用插件自己的 React 实例react-dom/client的createRoot把组件渲染进宿主提供的容器并用PluginErrorBoundary兜底渲染错误——updateId变化时错误边界会重置避免一次坏渲染把插件永久打成空白。类型注释types/viz.ts 的mount字段也明确宿主用该mount同时渲染可视化本体与每个设置 widget因为mount在沙箱内构造所以渲染始终走插件的 React 实例而静态渲染路径服务端 PNG/PDF不在 near-membrane 加固范围内。6.2 版本兼容的双层检测后端 manifest.clj 实现了两层软性版本校验compatible?用 npm/node-semver 范围语法如1.60.0、^1.60、1.59 1.61匹配metabase.version与当前 Metabase 版本未指定范围、开发模式或无版本信息时直接放行sdk-version-tested?以tested-sdk-version-range本仓库为2.0匹配sdk.version印章无印章视为 SDK 1.x 旧包。两者均只产生warnings如sdk-version-mismatch、metabase-version-mismatch从不阻断上传与运行警告文本会原样展示在管理后台。这解释了 CHANGELOG 中超出范围也不拒绝的行为设计。6.3 打包与资源约束pack.ts中MAX_COMPRESSED_BYTES与MAX_UNCOMPRESSED_BYTES两个常量即为后端上传限制的客户端映射。另外后端 manifest.clj 的asset-paths表明自定义可视化插件不会携带任意静态资源唯一可服务的资源是插件icon且必须是图片扩展名、相对路径且无目录穿越需要图片的插件作者应将图片内联如 base64进单个 JS bundle——这与 1.0.2 移除getAssetUrl的决策一脉相承。七、升级检查清单结合以上分析把现有插件升级到 2.0.0 可对照以下清单设置 id确认Settings类型与settings定义中没有column/column_settings有则重命名点击行为检查ClickObject相关代码是否读取.settings需移除复核旧卡片上已保存的click_behavior是否符合预期onChangeSettings移除对 Metabase 设置card.title等的写入尝试类型错误可辅助定位渲染上下文把props.colorScheme改为props.renderingContext.colorScheme删除对模块级measureText*的引用并改用renderingContext.measureTextdefineConfig删除可视化定义中的id字段构建脚本升级依赖build改为vite build metabase-custom-viz pack删除自带的pack.mjs与tar-stream相关 devDependencies验证npm run build产出.tgz上传验证上传后可在管理后台看到sdk.version印章若出现 SDK 版本或 Metabase 版本警告属非阻断提示可对照 manifest.clj 中的tested-sdk-version-range理解原因。【免费下载链接】metabaseThe easy-to-use open source Business Intelligence and Embedded Analytics tool that lets everyone work with data :bar_chart:项目地址: https://gitcode.com/GitHub_Trending/me/metabase创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表