跳到主内容

将插件从 Grafana 11.6.x 版本迁移到 12.0.x

本指南帮助您将插件从 Grafana 11.6.x 版本迁移到 12.0.x。

先决条件

开始迁移之前

  • 备份您的插件代码
  • 确保您的开发环境是最新的
  • 熟悉 Grafana 11.4 中引入的响应式 API

废弃的 UI 扩展 API 已移除

Grafana 12 中已移除废弃的 UI 扩展 API,取而代之的是 Grafana 11.4 中引入的新响应式 API。以下 API 已被移除

  • usePluginExtensions()
  • usePluginLinkExtensions()
  • usePluginComponentExtensions()
  • getPluginExtensions()
  • getPluginLinkExtensions()
  • getPluginComponentExtensions()
  • AppPlugin.configureExtensionLink()
  • AppPlugin.configureExtensionComponent()

在 Grafana 12 中使用任何这些 API 都将导致错误。此外,TypeScript 类型 PluginExtensionLinkConfigPluginExtensionComponentConfig 已被移除。

信息

如果您的插件需要同时兼容 Grafana 12.0.x 及更旧版本,您可以实现运行时检查以有条件地使用相应的 API。有关更多信息,请参阅使用运行时检查管理向后兼容性

configureExtensionLink 方法替换为 addLink 方法。将 extensionPointId 参数更新为 targets,该参数接受 stringstring[]

- new AppPlugin().configureExtensionLink({
+ new AppPlugin().addLink({
- extensionPointId: PluginExtensionPoints.DashboardPanelMenu,
+ targets: PluginExtensionPoints.DashboardPanelMenu,
title: 'Component title 0',
description: 'Component description 0',
component: () => <div />,
});

AppPlugin.configureExtensionComponent()

configureExtensionComponent 方法替换为 addComponent 方法。将 extensionPointId 参数更新为 targets,该参数接受 stringstring[]

- new AppPlugin().configureExtensionComponent({
+ new AppPlugin().addComponent({
- extensionPointId: PluginExtensionPoints.CommandPalette,
+ targets: PluginExtensionPoints.CommandPalette,
title: 'Component title 0',
description: 'Component description 0',
component: () => <div />,
});

getPluginLinkExtensions() 和 usePluginLinkExtensions()

getPluginLinkExtensions() 函数和 usePluginLinkExtensions() React Hook 都可以替换为 usePluginLinks() React Hook。

getPluginLinkExtensions
- const { extensions } = getPluginLinkExtensions({
+ const { links, isLoading } = usePluginLinks({
extensionPointId: 'grafana/dashboard/panel/menu/v1',
limitPerPlugin: 2,
context: {
panelId: '...',
},
});
usePluginLinkExtensions
- const { extensions, isLoading } = usePluginLinkExtensions({
+ const { links, isLoading } = usePluginLinks({
extensionPointId: 'grafana/dashboard/panel/menu/v1',
limitPerPlugin: 2,
context: {
panelId: '...',
},
});

getPluginComponentExtensions() 和 usePluginComponentExtensions()

您可以将 getPluginComponentExtensions() 函数和 usePluginComponentExtensions() React Hook 都替换为 usePluginComponents() React Hook。

getPluginComponentExtensions
- const { extensions } = getPluginComponentExtensions({
+ const { components, isLoading } = usePluginComponents({
extensionPointId: 'grafana/user/profile/tab/v1',
limitPerPlugin: 2,
});
usePluginComponentExtensions
- const { extensions, isLoading } = usePluginComponentExtensions({
+ const { components, isLoading } = usePluginComponents({
extensionPointId: 'grafana/user/profile/tab/v1',
limitPerPlugin: 2,
});

getPluginExtensions() 和 usePluginExtensions()

根据用途替换 getPluginExtensions() 函数和 usePluginExtensions() React Hook

  • 对于链接:遵循链接扩展说明。

  • 对于组件:遵循组件扩展说明。

  • 对于链接和组件:同时使用 usePluginLinksusePluginComponents

PluginExtensionLinkConfig 和 PluginExtensionComponentConfig

类型 PluginExtensionLinkConfigPluginExtensionComponentConfig 已从 @grafana/data 中移除。请分别替换为 PluginExtensionAddedLinkConfigPluginExtensionAddedComponentConfig

GetPluginExtensionsOptions

GetPluginExtensionsOptions 类型已从 @grafana/runtime 中移除,取而代之的是与相应 Hook 参数匹配的特定类型。

快速参考

下表总结了 API 的变化,并附带了说明关键差异的注释

已废弃的 API等效 API注释
AppPlugin.configureExtensionLink()AppPlugin.addLink()extensionPointId 参数重命名为 targets,接受 stringstring[]
AppPlugin.configureExtensionComponent()AppPlugin.addComponent()extensionPointId 参数重命名为 targets,接受 stringstring[]
getPluginLinkExtensions()usePluginLinks()返回 { links, isLoading } 而非 { extensions }
usePluginLinkExtensions()usePluginLinks()返回 { links, isLoading } 而非 { extensions }
getPluginComponentExtensions()usePluginComponents()返回 { components, isLoading } 而非 { extensions }
usePluginComponentExtensions()usePluginComponents()返回 { components, isLoading } 而非 { extensions, isLoading }
getPluginExtensions()usePluginLinks()usePluginComponents()根据扩展类型(链接或组件)拆分为两个独立的 Hook
usePluginExtensions()usePluginLinks()usePluginComponents()根据扩展类型(链接或组件)拆分为两个独立的 Hook
PluginExtensionComponentConfigPluginExtensionAddedComponentConfig组件配置的类型定义已更新
PluginExtensionLinkConfigPluginExtensionAddedLinkConfig链接配置的类型定义已更新
GetPluginExtensionsOptionsUsePluginLinksOptionsUsePluginComponentsOptionsUsePluginFunctionsOptionsHook 参数的类型定义已更新

Select 迁移到 Combobox

Grafana 11.5.0 引入了新的 Combobox 组件,作为 Select 组件的替代品。Combobox 组件在设计时考虑了性能,尤其适用于处理超大数据集。详细用法指南请参见组件文档

SelectMultiSelect 组件在 Grafana 12 中已被废弃,将不再获得重大更新或修复。建议迁移到 ComboboxMultiCombobox

基本用法

对于简单用例,Combobox 组件的 API 与 Select 类似。

/**
* Previous Select implementation
*/
import { SelectableValue } from '@grafana/data';
import { Select } from '@grafana/ui';

const options: SelectableValue[] = [
{ label: 'Loki', value: 'datasource-loki' },
{ label: 'Prometheus', value: 'datasource-prom' },
];
const [value, setValue] = useState<SelectableValue>();

<Select value={value} options={options} onChange={(newOption) => setValue(newOption)} />;

/**
* New Combobox implementation
*/
import { Combobox, ComboboxOption } from '@grafana/ui';

const options: ComboboxOption[] = [
{ label: 'Loki', value: 'datasource-loki' },
{ label: 'Prometheus', value: 'datasource-prom' },
];

// It is preferred to pass in only the 'value' property from options to the value prop
const [value, setValue] = useState<string>();

<Combobox value={value} options={options} onChange={(newOption) => setValue(newOption.value)} />;

异步数据加载

Combobox 组件通过传递给 options prop 的函数处理异步数据加载。此函数会

  • 接收当前输入值作为参数
  • 返回解析为 ComboboxOption[] 的 Promise
  • 自动防抖调用,以防止过多的 API 请求
import { Combobox, ComboboxOption } from '@grafana/ui';

const [value, setValue] = useState<string>();

const loadOptions = useCallback(async (input: string): Promise<ComboboxOption[]> => {
const response = await fetch(`/api/options?query=${input}`);
return response.json();
}, []);

<Combobox value={value} options={loadOptions} onChange={(newOption) => setValue(newOption.value)} />;
警告

首次打开时不要请求所有选项。建议仅在调用能够在服务器端过滤结果的 API 时使用此异步行为。

快速参考

下表总结了组件废弃的变化,并附带了说明关键差异的注释

已废弃等效项注释
SelectCombobox参见下方属性表
MultiSelectMultiCombobox参见下方属性表
AsyncSelectComboboxoptions prop 使用异步函数
VirtualizedSelectComboboxCombobox 默认支持虚拟化
AsyncVirtualizedSelectComboboxCombobox 默认支持虚拟化
AsyncMultiSelectMultiSelectoptions prop 使用异步函数

下表总结了属性的变化,并附带了说明关键差异的注释

已废弃等效项注释
SelectableValueComboboxOption改为从 @grafana/ui 导出
SelectableValue["value"]ComboboxOption["value"]Value 是必需的,并且必须是原始类型 string | number
SelectableValue["description"]ComboboxOption["description"]Description 不再换行,可能会被截断
onChangeonChange建议只在 state 中存储 value
valuevalue建议只传入原始类型 string | number 的值
optionsoptions可以是 ComboboxOption[] 或返回 Promise<ComboboxOption[]> 的函数
isLoadingloading如果使用异步 options 则不是必需的
allowCustomValuecreateCustomValueonChange 会发出一个类似 { label: "Foo", value: "Foo" } 的对象
width="auto"width="auto"使用自动调整大小的输入框时,需要 minWidth

旧 Select 组件中许多控制微小行为或自定义渲染的属性(例如 createOptionPositionopenMenuOnFocus)不再受支持,以简化 API 并提供更一致的体验。如果您有需要此功能的特定用例,请在 Grafana 仓库中提交一个 issue