Updated Migrating Apps Guide
Signed-off-by: Andre Wanlin <awanlin@spotify.com>
This commit is contained in:
@@ -12,7 +12,13 @@ This section describes how to migrate an existing Backstage app package to use t
|
||||
|
||||
## Switching out `createApp`
|
||||
|
||||
The first step in migrating an app is to switch out the `createApp` function for the new one from `@backstage/frontend-api-app`:
|
||||
To start we'll need to add the new `@backstage/frontend-defaults` package:
|
||||
|
||||
```bash
|
||||
yarn --cwd packages/app add @backstage/frontend-defaults
|
||||
```
|
||||
|
||||
The next step in migrating an app is to switch out the `createApp` function for the new one from `@backstage/frontend-defaults`:
|
||||
|
||||
```tsx title="in packages/app/src/App.tsx"
|
||||
// highlight-remove-next-line
|
||||
@@ -61,7 +67,7 @@ import {
|
||||
|
||||
const legacyFeatures = convertLegacyApp(
|
||||
<>
|
||||
<AlertDisplay transientTimeoutMs={2500} />
|
||||
<AlertDisplay />
|
||||
<OAuthRequestDialog />
|
||||
<AppRouter>
|
||||
<Root>{routes}</Root>
|
||||
@@ -70,7 +76,7 @@ const legacyFeatures = convertLegacyApp(
|
||||
);
|
||||
|
||||
const optionsModule = convertLegacyAppOptions({
|
||||
/* other options */
|
||||
/* other options such as apis, plugins, components, and themes */
|
||||
});
|
||||
|
||||
const app = createApp({
|
||||
@@ -98,6 +104,44 @@ ReactDOM.createRoot(document.getElementById('root')!).render(<App />);
|
||||
ReactDOM.createRoot(document.getElementById('root')!).render(app);
|
||||
```
|
||||
|
||||
You'll also need to make similar changes to your `App.test.tsx` file as well:
|
||||
|
||||
```tsx
|
||||
import { render, waitFor } from '@testing-library/react';
|
||||
// highlight-remove-next-line
|
||||
import App from './App';
|
||||
// highlight-add-next-line
|
||||
import app from './App';
|
||||
|
||||
describe('App', () => {
|
||||
it('should render', async () => {
|
||||
process.env = {
|
||||
NODE_ENV: 'test',
|
||||
APP_CONFIG: [
|
||||
{
|
||||
data: {
|
||||
app: { title: 'Test' },
|
||||
backend: { baseUrl: 'http://localhost:7007' },
|
||||
},
|
||||
context: 'test',
|
||||
},
|
||||
] as any,
|
||||
};
|
||||
|
||||
// highlight-remove-next-line
|
||||
const rendered = render(<App />);
|
||||
// highlight-add-next-line
|
||||
const rendered = render(app);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(rendered.baseElement).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
Then you'll want to follow the section on [migrating `bindRoutes`](#bindroutes).
|
||||
|
||||
At this point the contents of your app should be past the initial migration stage, and we can move on to migrating any remaining options that you may have passed to `createApp`.
|
||||
|
||||
## Migrating `createApp` Options
|
||||
@@ -106,7 +150,17 @@ Many of the `createApp` options have been migrated to use extensions instead. Ea
|
||||
|
||||
For example, assuming you have a `lightTheme` extension that you want to add to your app, you can use the following:
|
||||
|
||||
First we add the `@backstage/frontend-plugin-api` package
|
||||
|
||||
```bash
|
||||
yarn --cwd packages/app add @backstage/frontend-plugin-api
|
||||
```
|
||||
|
||||
Then we can use it like this:
|
||||
|
||||
```ts
|
||||
import { createFrontendModule } from '@backstage/frontend-plugin-api';
|
||||
|
||||
const app = createApp({
|
||||
features: [
|
||||
// highlight-add-start
|
||||
@@ -142,6 +196,8 @@ const app = createApp({
|
||||
Can be converted to the following extension:
|
||||
|
||||
```ts
|
||||
import { ApiBlueprint } from '@backstage/frontend-plugin-api';
|
||||
|
||||
const scmIntegrationsApi = ApiBlueprint.make({
|
||||
name: 'scm-integrations',
|
||||
params: {
|
||||
@@ -154,9 +210,7 @@ const scmIntegrationsApi = ApiBlueprint.make({
|
||||
});
|
||||
```
|
||||
|
||||
### `icons`
|
||||
|
||||
Icons are currently installed through the usual options to `createApp`, but will be switched to use extensions in the future.
|
||||
You would then add `scmIntegrationsApi` as an `extension` like you did with `lightTheme` in the [Migrating `createApp` Options](#migrating-createapp-options) section.
|
||||
|
||||
### `plugins`
|
||||
|
||||
@@ -192,7 +246,8 @@ Plugins don't even have to be imported manually after installing their package i
|
||||
```yaml title="in app-config.yaml"
|
||||
app:
|
||||
# Enabling plugin and override features discovery
|
||||
experimental: 'all'
|
||||
experimental:
|
||||
packages: all # ✨
|
||||
```
|
||||
|
||||
### `featureFlags`
|
||||
@@ -218,6 +273,8 @@ createApp({
|
||||
Can be converted to the following plugin configuration:
|
||||
|
||||
```tsx
|
||||
import { createFrontendPlugin } from '@backstage/frontend-plugin-api';
|
||||
|
||||
createFrontendPlugin({
|
||||
pluginId: 'tech-radar',
|
||||
// ...
|
||||
@@ -226,6 +283,8 @@ createFrontendPlugin({
|
||||
});
|
||||
```
|
||||
|
||||
This would get added to the `features` array as part of your `createApp` options.
|
||||
|
||||
### `components`
|
||||
|
||||
Many app components are now installed as extensions instead using `createComponentExtension`. See the section on [configuring app components](./01-index.md#configure-your-app) for more information.
|
||||
@@ -257,6 +316,8 @@ const app = createApp({
|
||||
Can be converted to the following extension:
|
||||
|
||||
```tsx
|
||||
import { SignInPageBlueprint } from '@backstage/frontend-plugin-api';
|
||||
|
||||
const signInPage = SignInPageBlueprint.make({
|
||||
params: {
|
||||
loader: async () => props =>
|
||||
@@ -275,6 +336,8 @@ const signInPage = SignInPageBlueprint.make({
|
||||
});
|
||||
```
|
||||
|
||||
You would then add `signInPage` as an `extension` like you did with `lightTheme` in the [Migrating `createApp` Options](#migrating-createapp-options) section.
|
||||
|
||||
### `themes`
|
||||
|
||||
Themes are now installed as extensions, created using `ThemeBlueprint`.
|
||||
@@ -285,7 +348,7 @@ For example, the following theme configuration:
|
||||
const app = createApp({
|
||||
themes: [
|
||||
{
|
||||
id: 'light',
|
||||
id: 'custom-light',
|
||||
title: 'Light',
|
||||
variant: 'light',
|
||||
Provider: ({ children }) => (
|
||||
@@ -301,27 +364,33 @@ const app = createApp({
|
||||
Can be converted to the following extension:
|
||||
|
||||
```tsx
|
||||
const lightTheme = ThemeBlueprint.make({
|
||||
name: 'light',
|
||||
import { ThemeBlueprint } from '@backstage/frontend-plugin-api';
|
||||
|
||||
const customLightThemeExtension = ThemeBlueprint.make({
|
||||
name: 'custom-light',
|
||||
params: {
|
||||
theme: {
|
||||
id: 'light',
|
||||
id: 'custom-light',
|
||||
title: 'Light Theme',
|
||||
variant: 'light',
|
||||
icon: <LightIcon />,
|
||||
Provider: ({ children }) => (
|
||||
<UnifiedThemeProvider theme={builtinThemes.light} children={children} />
|
||||
<UnifiedThemeProvider theme={customLightTheme} children={children} />
|
||||
),
|
||||
},
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
You would then add `customLightThemeExtension` as an `extension` like you did with `lightTheme` in the [Migrating `createApp` Options](#migrating-createapp-options) section.
|
||||
|
||||
### `configLoader`
|
||||
|
||||
The config loader API has been slightly changed. Rather than returning a promise for an array of `AppConfig` objects, it should now return the `ConfigApi` directly.
|
||||
|
||||
```ts
|
||||
import { ConfigReader } from '@backstage/core-app-api';
|
||||
|
||||
const app = createApp({
|
||||
async configLoader() {
|
||||
const appConfigs = await loadAppConfigs();
|
||||
@@ -403,7 +472,13 @@ createApp({
|
||||
Can be converted to the following extension:
|
||||
|
||||
```tsx
|
||||
TranslationBlueprint.make({
|
||||
import { catalogTranslationRef } from '@backstage/plugin-catalog/alpha';
|
||||
import {
|
||||
createTranslationMessages,
|
||||
TranslationBlueprint,
|
||||
} from '@backstage/frontend-plugin-api';
|
||||
|
||||
const catalogTranslations = TranslationBlueprint.make({
|
||||
name: 'catalog-overrides',
|
||||
params: {
|
||||
resource: createTranslationMessages({
|
||||
@@ -414,6 +489,8 @@ TranslationBlueprint.make({
|
||||
});
|
||||
```
|
||||
|
||||
You would then add `catalogTranslations` as an `extension` like you did with `lightTheme` in the [Migrating `createApp` Options](#migrating-createapp-options) section.
|
||||
|
||||
## Gradual Migration
|
||||
|
||||
After updating all `createApp` options as well as using `convertLegacyApp` to use your existing app structure, you should be able to start up the app and see that it still works. If that is not the case, make sure you read any error messages that you may see in the app as they can provide hints on what you need to fix. If you are still stuck, you can check if anyone else ran into the same issue in our [GitHub issues](https://github.com/backstage/backstage/issues), or ask for help in our [community Discord](https://discord.gg/backstage-687207715902193673).
|
||||
@@ -425,7 +502,7 @@ First off we'll want to trim away any top-level elements in the app so that only
|
||||
```tsx title="in packages/app/src/App.tsx"
|
||||
const legacyFeatures = convertLegacyApp(
|
||||
<>
|
||||
<AlertDisplay transientTimeoutMs={2500} />
|
||||
<AlertDisplay />
|
||||
<OAuthRequestDialog />
|
||||
<AppRouter>
|
||||
<Root>{routes}</Root>
|
||||
|
||||
Reference in New Issue
Block a user