Migrating Plugins
This guide allows you to migrate a frontend plugin and its own components, routes, apis to the new frontend system.
The main concept is that routes, components, apis are now extensions. You can use the appropriate extension blueprints to migrate all of them to extensions.
Migrating the plugin
Unless you are migrating a plugin that is only used within your own project, we recommend all plugins to keep support for the old system intact. The code added in these examples should be added to a new src/alpha.tsx entry point of your plugin.
In the legacy frontend system a plugin was defined in its own plugin.ts file as following:
import { createPlugin } from '@backstage/core-plugin-api';
export const myPlugin = createPlugin({
id: 'my-plugin',
apis: [ ... ],
routes: {
...
},
externalRoutes: {
...
},
});
In order to migrate the actual definition of the plugin you need to recreate the plugin using the new createFrontendPlugin utility exported by @backstage/frontend-plugin-api. The new createFrontendPlugin function doesn't accept apis anymore as apis are now extensions.
import { createFrontendPlugin } from '@backstage/frontend-plugin-api';
export default createFrontendPlugin({
// The plugin ID is now provided as `pluginId` instead of `id`
pluginId: 'my-plugin',
// bind all the extensions to the plugin
extensions: [/* APIs will go here, but don't worry about those yet */],
routes: {
...
},
externalRoutes: {
...
},
});
The code above binds all the extensions to the plugin. Important: Make sure to export the plugin as default export of your package as a separate entrypoint, preferably /alpha, as suggested by the code snippet above. Make sure src/alpha.tsx is exported in your package.json:
"exports": {
".": "./src/index.ts",
"./alpha": "./src/alpha.tsx",
"./package.json": "./package.json"
},
"typesVersions": {
"*": {
"alpha": [
"src/alpha.tsx"
],
"package.json": [
"package.json"
]
}
},
Migrating Pages
Pages that were previously created using the createRoutableExtension extension function can be migrated to the new Frontend System using the PageBlueprint extension blueprint, exported by @backstage/frontend-plugin-api.
In the new system plugins provide more information than they used to. For example, the plugin is now responsible for providing the path for the page, rather than it being part of the app code.
For example, given the following page:
export const FooPage = fooPlugin.provide(
createRoutableExtension({
name: 'FooPage',
component: () => import('./components').then(m => m.FooPage),
mountPoint: rootRouteRef,
}),
);
and the following instruction in the plugin README:
<Route path="/foo" element={<FooPage />} />
it can be migrated as the following, keeping in mind that you may need to switch from .ts to .tsx:
import { PageBlueprint } from '@backstage/frontend-plugin-api';
const fooPage = PageBlueprint.make({
params: {
// This is the path that was previously defined in the app code.
// It's labelled as the default one because it can be changed via configuration.
path: '/foo',
// You can reuse the existing routeRef.
routeRef: rootRouteRef,
// these inputs usually match the props required by the component.
loader: () => import('./components/').then(m => <m.FooPage />),
},
});
Then add the fooPage extension to the plugin:
import { createFrontendPlugin } from '@backstage/frontend-plugin-api';
export default createFrontendPlugin({
pluginId: 'my-plugin',
// bind all the extensions to the plugin
extensions: [],
extensions: [fooPage],
...
});