From 49c90562f8efb58946b4c98189a9488cc24f0979 Mon Sep 17 00:00:00 2001 From: Brian Smith Date: Wed, 21 Jan 2026 16:32:12 -0500 Subject: [PATCH] feat!: update runtime config support BREAKING CHANGE: rename `mfeConfigApiUrl` to `runtimeConfigJsonUrl` BREAKING CHANGE: remove `siteId` from config URL building add cache buster for development environments --- docs/how_tos/migrate-frontend-app.md | 2 +- runtime/config/index.ts | 4 ++-- runtime/initialize.js | 17 +++++++++++------ runtime/initialize.test.js | 4 ++-- shell/site.config.dev.tsx | 2 +- test-site/site.config.build.tsx | 2 +- test-site/site.config.dev.tsx | 2 +- types.ts | 2 +- 8 files changed, 20 insertions(+), 15 deletions(-) diff --git a/docs/how_tos/migrate-frontend-app.md b/docs/how_tos/migrate-frontend-app.md index 890cca7c..ed8e568d 100644 --- a/docs/how_tos/migrate-frontend-app.md +++ b/docs/how_tos/migrate-frontend-app.md @@ -609,7 +609,7 @@ Other configuration is now optional, and many values have been given sensible de - environment: EnvironmentTypes - basename: string -- mfeConfigApiUrl: string | null +- runtimeConfigJsonUrl: string | null - accessTokenCookieName: string - languagePreferenceCookieName: string - userInfoCookieName: string diff --git a/runtime/config/index.ts b/runtime/config/index.ts index 1222c0fb..8399d239 100644 --- a/runtime/config/index.ts +++ b/runtime/config/index.ts @@ -88,7 +88,7 @@ * * https://github.com/openedx/edx-platform/blob/master/lms/djangoapps/mfe_config_api/docs/decisions/0001-mfe-config-api.rst * - * The runtime configuration method can be enabled by supplying a mfeConfigApiUrl via one of the other + * The runtime configuration method can be enabled by supplying a runtimeConfigJsonUrl via one of the other * two configuration methods above. * * Runtime configuration is particularly useful if you need to supply different configurations to @@ -123,7 +123,7 @@ let siteConfig: SiteConfig = { apps: [], externalRoutes: [], externalLinkUrlOverrides: [], - mfeConfigApiUrl: null, + runtimeConfigJsonUrl: null, theme: {}, accessTokenCookieName: 'edx-jwt-cookie-header-payload', csrfTokenApiPath: '/csrf/api/v1/token', diff --git a/runtime/initialize.js b/runtime/initialize.js index 9030d820..461ea0a2 100644 --- a/runtime/initialize.js +++ b/runtime/initialize.js @@ -90,6 +90,7 @@ import { } from './logging'; import { GoogleAnalyticsLoader } from './scripts'; import { publish } from './subscriptions'; +import { EnvironmentTypes } from '../types'; /** * If set in configuration, a basename will be prepended to all relative routes under BrowserRouter. @@ -165,17 +166,21 @@ async function fileConfig() { */ async function runtimeConfig() { try { - const { mfeConfigApiUrl, siteId } = getSiteConfig(); + const { runtimeConfigJsonUrl, environment } = getSiteConfig(); - if (mfeConfigApiUrl) { + if (runtimeConfigJsonUrl) { const apiConfig = { headers: { accept: 'application/json' } }; const apiService = await configureCache(); - const params = new URLSearchParams(); - params.append('mfe', siteId); - const url = `${mfeConfigApiUrl}?${params.toString()}`; + const runtimeConfigUrl = new URL(runtimeConfigJsonUrl); - const { data } = await apiService.get(url, apiConfig); + // In development mode, add a timestamp as a cache buster + // to support live-editing runtime config JSON + if (environment === EnvironmentTypes.DEVELOPMENT) { + runtimeConfigUrl.searchParams.set('timestamp', Date.now()); + } + + const { data } = await apiService.get(runtimeConfigUrl.toString(), apiConfig); mergeSiteConfig(data); } } catch (error) { diff --git a/runtime/initialize.test.js b/runtime/initialize.test.js index b75f9b89..38627a76 100644 --- a/runtime/initialize.test.js +++ b/runtime/initialize.test.js @@ -274,7 +274,7 @@ describe('initialize', () => { handlers: { config: () => { mergeSiteConfig({ - mfeConfigApiUrl: 'http://localhost:18000/api/mfe/v1/config', + runtimeConfigJsonUrl: 'http://localhost:18000/api/mfe/v1/config', siteId: 'auth', }); } @@ -324,7 +324,7 @@ describe('initialize', () => { handlers: { config: () => { mergeSiteConfig({ - mfeConfigApiUrl: 'http://localhost:18000/api/mfe/v1/config', + runtimeConfigJsonUrl: 'http://localhost:18000/api/mfe/v1/config', siteId: 'auth', }); } diff --git a/shell/site.config.dev.tsx b/shell/site.config.dev.tsx index 32f29527..63ebed95 100644 --- a/shell/site.config.dev.tsx +++ b/shell/site.config.dev.tsx @@ -43,7 +43,7 @@ const siteConfig: SiteConfig = { // API URLs lmsBaseUrl: 'http://local.openedx.io:8000', - mfeConfigApiUrl: 'http://apps.local.openedx.io:8080/api/mfe_config/v1', + runtimeConfigJsonUrl: 'http://apps.local.openedx.io:8080/api/mfe_config/v1', }; export default siteConfig; diff --git a/test-site/site.config.build.tsx b/test-site/site.config.build.tsx index 7aeffedc..abd9585a 100644 --- a/test-site/site.config.build.tsx +++ b/test-site/site.config.build.tsx @@ -13,7 +13,7 @@ const siteConfig: SiteConfig = { logoutUrl: 'http://local.openedx.io:8000/logout', environment: EnvironmentTypes.PRODUCTION, - mfeConfigApiUrl: 'http://apps.local.openedx.io:8080/api/mfe_config/v1', + runtimeConfigJsonUrl: 'http://apps.local.openedx.io:8080/api/mfe_config/v1', apps: [ shellApp, headerApp, diff --git a/test-site/site.config.dev.tsx b/test-site/site.config.dev.tsx index e6feff4f..41bfcb24 100644 --- a/test-site/site.config.dev.tsx +++ b/test-site/site.config.dev.tsx @@ -13,7 +13,7 @@ const siteConfig: SiteConfig = { logoutUrl: 'http://local.openedx.io:8000/logout', environment: EnvironmentTypes.DEVELOPMENT, - mfeConfigApiUrl: 'http://apps.local.openedx.io:8080/api/mfe_config/v1', + runtimeConfigJsonUrl: 'http://apps.local.openedx.io:8080/api/mfe_config/v1', apps: [ shellApp, headerApp, diff --git a/types.ts b/types.ts index 77c5cd58..6fd051fc 100644 --- a/types.ts +++ b/types.ts @@ -58,7 +58,7 @@ export interface OptionalSiteConfig { basename: string, externalRoutes: ExternalRoute[], externalLinkUrlOverrides: string[], - mfeConfigApiUrl: string | null, + runtimeConfigJsonUrl: string | null, // Theme theme: Theme,