Merge pull request #26555 from backstage/blam/doc-updates

NFS: Doc updates to use `createFrontendModule` instead of `createExtensionOverrides`
This commit is contained in:
Ben Lambert
2024-09-10 10:30:33 +02:00
committed by GitHub
8 changed files with 182 additions and 106 deletions
@@ -263,23 +263,19 @@ const overrideExtension = exampleExtension.override({
To install extension overrides in a Backstage app you should use `plugin.withOverrides` whenever you are overriding or adding extensions for a plugin. See the section on [overriding a plugin](./15-plugins.md#overriding-a-plugin) for more information.
There is also a `createExtensionOverrides` function that can be used to install a collection of standalone extensions in an app. This method will be replaced with a different mechanism in the future, but for now remains the only way to override the built-in extensions in the app or to package extensions for a plugin package separate from the plugin itself.
Note that while using either of these options you don't necessarily need to use the extension `.override(...)` method to create the overrides. You can also create new extensions with `createExtension` or a blueprint that are either completely net-new extensions, or override an existing extension by using the same `kind`, `namespace` and `name` to produce the same extension ID.
### Creating a standalone extension bundle
### Creating a frontend module
The following example shows how to create a standalone extension bundle that overrides the search page from the search plugin:
The following example shows how to create a frontend module that overrides the search page from the search plugin:
```tsx
import {
createPageExtension,
createExtensionOverrides,
createFrontendModule,
} from '@backstage/frontend-plugin-api';
const customSearchPage = PageBlueprint.make({
// Since this is a standalone extension we need to provide the namespace to match the search plugin
namespace: 'search',
params: {
defaultPath: '/search',
loader: () =>
@@ -287,7 +283,8 @@ const customSearchPage = PageBlueprint.make({
},
});
export default createExtensionOverrides({
export default createFrontendModule({
pluginId: 'search',
extensions: [customSearchPage],
});
```
@@ -296,12 +293,14 @@ Assuming the above code resides in the `@internal/search-page` package, you can
```tsx title="packages/app/src/App.tsx"
import { createApp } from '@backstage/frontend-defaults';
import searchPageOverride from '@internal/search-page';
import searchPageModule from '@internal/search-page';
const app = createApp({
// highlight-next-line
features: [searchPageOverride],
features: [searchPageModule],
});
export default app.createRoot();
```
You must define a `pluginId` when creating a frontend module, and the plugin must also be installed for the module to be loaded.
@@ -14,6 +14,60 @@ This section provides migration guides for different versions of the frontend sy
This guide is intended for app and plugin authors who have already migrated their code to the new frontend system, and are looking to keep it up to date with the latest changes. These guides do not cover trivial migrations that can be explained in a deprecation message, such as a renamed export.
## 1.31.0
### `namespace` parameter should be removed
The `namespace` parameter to all `createExtension`, `createExtensionBlueprint` or any `.make()` or `.makeWithOverrides()` method can be removed. This will now default to the `id` of the `plugin` which should already be the case.
### `createExtensionOverrides` -> `createFrontendModule`
Extensions will need to be wrapped in a module in order to be installed in the frontend. This means that the `createExtensionOverrides` function should be replaced with `createFrontendModule`, and the `pluginId` parameter should be set with the target `pluginId` that you're overriding.
For example:
```tsx
import {
createPageExtension,
createExtensionOverrides,
} from '@backstage/frontend-plugin-api';
const customSearchPage = PageBlueprint.make({
namespace: 'search',
params: {
defaultPath: '/search',
loader: () =>
import('./CustomSearchPage').then(m => <m.CustomSearchPage />),
},
});
export default createExtensionOverrides({
extensions: [customSearchPage],
});
```
Should now look like this:
```tsx
import {
createPageExtension,
createFrontendModule,
} from '@backstage/frontend-plugin-api';
const customSearchPage = PageBlueprint.make({
params: {
defaultPath: '/search',
loader: () =>
import('./CustomSearchPage').then(m => <m.CustomSearchPage />),
},
});
export default createFrontendModule({
pluginId: 'search',
extensions: [customSearchPage],
});
```
## 1.30
### Reworked extension inputs and outputs
@@ -95,7 +95,7 @@ At this point the contents of your app should be past the initial migration stag
## Migrating `createApp` Options
Many of the `createApp` options have been migrated to use extensions instead. Each will have their own [extension blueprint](../architecture/23-extension-blueprints.md) that you use to create a custom extension. To add these standalone extensions to the app they need to be passed to `createExtensionOverrides`, which bundles them into a _feature_ that you can install in the app. See the [standalone extensions](../architecture/25-extension-overrides.md#creating-a-standalone-extension-bundle) section for more information.
Many of the `createApp` options have been migrated to use extensions instead. Each will have their own [extension blueprint](../architecture/23-extension-blueprints.md) that you use to create a custom extension. To add these standalone extensions to the app they need to be passed to `createFrontendModule`, which bundles them into a _feature_ that you can install in the app. See the [frontend module](../architecture/25-extension-overrides.md#creating-a-frontend-module) section for more information.
For example, assuming you have a `lightTheme` extension that you want to add to your app, you can use the following:
@@ -103,7 +103,8 @@ For example, assuming you have a `lightTheme` extension that you want to add to
const app = createApp({
features: [
// highlight-add-start
createExtensionOverrides({
createFrontendModule({
pluginId: 'app',
extensions: [lightTheme],
}),
// highlight-add-end
@@ -343,7 +344,8 @@ const exampleIconBundle = IconBundleBlueprint.make({
const app = createApp({
features: [
createExtensionOverrides({
createFrontendModule({
pluginId: 'app',
extensions: [exampleIconBundle],
}),
],
@@ -568,7 +570,8 @@ Here is an example converting the `CustomAppBarrier` into extension:
createApp({
// ...
features: [
createExtensionOverrides({
createFrontendModule({
pluginId: 'app',
extensions: [
AppRootWrapperBlueprint.make({
name: 'custom-app-barrier',
@@ -41,13 +41,14 @@ Like with other extension types, you replace Utility APIs with your own custom i
```tsx title="in your app"
/* highlight-add-start */
import { createExtensionOverrides } from '@backstage/frontend-plugin-api';
import { createFrontendModule } from '@backstage/frontend-plugin-api';
class CustomWorkImpl implements WorkApi {
/* ... */
}
const myOverrides = createExtensionOverrides({
const workModule = createFrontendModule({
pluginId: 'work',
extensions: [
ApiBlueprint.make({
params: {
@@ -66,7 +67,7 @@ export default createApp({
features: [
// ... other features
/* highlight-add-next-line */
myOverrides,
workModule,
],
});
```