core-app-api: immediately register discovered feature flags
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/core-app-api': patch
|
||||
---
|
||||
|
||||
Tweak feature flag registration so that it happens immediately before the first rendering of the app, rather than just after.
|
||||
@@ -34,6 +34,7 @@ import {
|
||||
createSubRouteRef,
|
||||
createRoutableExtension,
|
||||
analyticsApiRef,
|
||||
useApi,
|
||||
} from '@backstage/core-plugin-api';
|
||||
import { AppManager } from './AppManager';
|
||||
import { AppComponents, AppIcons } from './types';
|
||||
@@ -395,6 +396,44 @@ describe('Integration Test', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('feature flags should be available immediately', async () => {
|
||||
const app = new AppManager({
|
||||
apis: [
|
||||
createApiFactory({
|
||||
api: featureFlagsApiRef,
|
||||
deps: { configApi: configApiRef },
|
||||
factory() {
|
||||
return new LocalStorageFeatureFlags();
|
||||
},
|
||||
}),
|
||||
],
|
||||
defaultApis: [],
|
||||
themes,
|
||||
icons,
|
||||
plugins: [createPlugin({ id: 'test', featureFlags: [{ name: 'foo' }] })],
|
||||
components,
|
||||
configLoader: async () => [],
|
||||
});
|
||||
|
||||
const Provider = app.getProvider();
|
||||
const Router = app.getRouter();
|
||||
|
||||
const FeatureFlags = () => {
|
||||
const featureFlags = useApi(featureFlagsApiRef).getRegisteredFlags();
|
||||
return <div>Flags: {featureFlags.map(f => f.name).join(',')}</div>;
|
||||
};
|
||||
|
||||
await renderWithEffects(
|
||||
<Provider>
|
||||
<Router>
|
||||
<FeatureFlags />
|
||||
</Router>
|
||||
</Provider>,
|
||||
);
|
||||
|
||||
expect(screen.getByText('Flags: foo')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should track route changes via analytics api', async () => {
|
||||
const mockAnalyticsApi = new MockAnalyticsApi();
|
||||
const apis = [createApiFactory(analyticsApiRef, mockAnalyticsApi)];
|
||||
|
||||
@@ -21,8 +21,8 @@ import React, {
|
||||
PropsWithChildren,
|
||||
ReactElement,
|
||||
useContext,
|
||||
useEffect,
|
||||
useMemo,
|
||||
useRef,
|
||||
useState,
|
||||
} from 'react';
|
||||
import { Route, Routes } from 'react-router-dom';
|
||||
@@ -230,6 +230,7 @@ export class AppManager implements BackstageApp {
|
||||
let routesHaveBeenValidated = false;
|
||||
|
||||
const Provider = ({ children }: PropsWithChildren<{}>) => {
|
||||
const needsFeatureFlagRegistrationRef = useRef(true);
|
||||
const appThemeApi = useMemo(
|
||||
() => AppThemeSelector.createWithStorage(this.themes),
|
||||
[],
|
||||
@@ -284,10 +285,21 @@ export class AppManager implements BackstageApp {
|
||||
this.configApi = api;
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (hasConfigApi) {
|
||||
const featureFlagsApi = this.getApiHolder().get(featureFlagsApiRef)!;
|
||||
if ('node' in loadedConfig) {
|
||||
// Loading or error
|
||||
return loadedConfig.node;
|
||||
}
|
||||
|
||||
// We can't register feature flags just after the element traversal, because the
|
||||
// config API isn't available yet and implementations frequently depend on it.
|
||||
// Instead we make it happen immediately, to make sure all flags are available
|
||||
// for the first render.
|
||||
if (hasConfigApi && needsFeatureFlagRegistrationRef.current) {
|
||||
needsFeatureFlagRegistrationRef.current = false;
|
||||
|
||||
const featureFlagsApi = this.getApiHolder().get(featureFlagsApiRef)!;
|
||||
|
||||
if (featureFlagsApi) {
|
||||
for (const plugin of this.plugins.values()) {
|
||||
if ('getFeatureFlags' in plugin) {
|
||||
for (const flag of plugin.getFeatureFlags()) {
|
||||
@@ -314,11 +326,6 @@ export class AppManager implements BackstageApp {
|
||||
featureFlagsApi.registerFlag({ name, pluginId: '' });
|
||||
}
|
||||
}
|
||||
}, [hasConfigApi, loadedConfig, featureFlags]);
|
||||
|
||||
if ('node' in loadedConfig) {
|
||||
// Loading or error
|
||||
return loadedConfig.node;
|
||||
}
|
||||
|
||||
const { ThemeProvider = AppThemeProvider } = this.components;
|
||||
|
||||
Reference in New Issue
Block a user