diff --git a/packages/cli/src/commands/start/startFrontend.ts b/packages/cli/src/commands/start/startFrontend.ts index 536b313dfe..2cc951f591 100644 --- a/packages/cli/src/commands/start/startFrontend.ts +++ b/packages/cli/src/commands/start/startFrontend.ts @@ -14,11 +14,9 @@ * limitations under the License. */ -import fs from 'fs-extra'; import chalk from 'chalk'; import uniq from 'lodash/uniq'; import { serveBundle } from '../../lib/bundler'; -import { loadCliConfig } from '../../lib/config'; import { PackageGraph } from '@backstage/cli-node'; import { Lockfile } from '../../lib/versioning'; import { forbiddenDuplicatesFilter, includedFilter } from '../versions/lint'; @@ -91,41 +89,10 @@ export async function startFrontend(options: StartAppOptions) { checkReactVersion(); - const configChannel = new MessageChannel(); - - const { name } = await fs.readJson(paths.resolveTarget('package.json')); - const config = await loadCliConfig({ - args: options.configPaths, - fromPackage: name, - withFilteredKeys: true, - watch(appConfigs) { - configChannel.port1.postMessage(appConfigs); - }, - }); - - const appBaseUrl = config.frontendConfig.getString('app.baseUrl'); - const backendBaseUrl = config.frontendConfig.getString('backend.baseUrl'); - if (appBaseUrl === backendBaseUrl) { - console.log( - chalk.yellow( - `⚠️ Conflict between app baseUrl and backend baseUrl: - - app.baseUrl: ${appBaseUrl} - backend.baseUrl: ${backendBaseUrl} - - Must have unique hostname and/or ports. - - This can be resolved by changing app.baseUrl and backend.baseUrl to point to their respective local development ports. -`, - ), - ); - } - const waitForExit = await serveBundle({ entry: options.entry, checksEnabled: options.checksEnabled, - configChannel, - ...config, + configPaths: options.configPaths, }); await waitForExit(); diff --git a/packages/cli/src/lib/bundler/bundle.ts b/packages/cli/src/lib/bundler/bundle.ts index b26c2f9f0d..7c45528c5c 100644 --- a/packages/cli/src/lib/bundler/bundle.ts +++ b/packages/cli/src/lib/bundler/bundle.ts @@ -45,6 +45,7 @@ export async function buildBundle(options: BuildOptions) { checksEnabled: false, isDev: false, baseUrl: resolveBaseUrl(options.frontendConfig), + getFrontendAppConfigs: () => options.frontendAppConfigs, }); const isCi = yn(process.env.CI, { default: false }); diff --git a/packages/cli/src/lib/bundler/server.ts b/packages/cli/src/lib/bundler/server.ts index bef1a6fd7a..2ac717243f 100644 --- a/packages/cli/src/lib/bundler/server.ts +++ b/packages/cli/src/lib/bundler/server.ts @@ -21,27 +21,64 @@ import openBrowser from 'react-dev-utils/openBrowser'; import { createConfig, resolveBaseUrl } from './config'; import { ServeOptions } from './types'; import { resolveBundlingPaths } from './paths'; +import { paths as libPaths } from '../../lib/paths'; +import { loadCliConfig } from '../config'; +import chalk from 'chalk'; import { AppConfig } from '@backstage/config'; export async function serveBundle(options: ServeOptions) { - const url = resolveBaseUrl(options.frontendConfig); + const { name } = await fs.readJson(libPaths.resolveTarget('package.json')); + + let server: WebpackDevServer | undefined = undefined; + let latestFrontendAppConfigs: AppConfig[] = []; + + const cliConfig = await loadCliConfig({ + args: options.configPaths, + fromPackage: name, + withFilteredKeys: true, + watch(appConfigs) { + latestFrontendAppConfigs = appConfigs; + server?.invalidate(); + }, + }); + latestFrontendAppConfigs = cliConfig.frontendAppConfigs; + + const appBaseUrl = cliConfig.frontendConfig.getString('app.baseUrl'); + const backendBaseUrl = cliConfig.frontendConfig.getString('backend.baseUrl'); + if (appBaseUrl === backendBaseUrl) { + console.log( + chalk.yellow( + `⚠️ Conflict between app baseUrl and backend baseUrl: + + app.baseUrl: ${appBaseUrl} + backend.baseUrl: ${backendBaseUrl} + + Must have unique hostname and/or ports. + + This can be resolved by changing app.baseUrl and backend.baseUrl to point to their respective local development ports. +`, + ), + ); + } + + const { frontendConfig, fullConfig } = cliConfig; + const url = resolveBaseUrl(frontendConfig); const host = - options.frontendConfig.getOptionalString('app.listen.host') || url.hostname; + frontendConfig.getOptionalString('app.listen.host') || url.hostname; const port = - options.frontendConfig.getOptionalNumber('app.listen.port') || + frontendConfig.getOptionalNumber('app.listen.port') || Number(url.port) || (url.protocol === 'https:' ? 443 : 80); - let latestFrontendAppConfigs = options.frontendAppConfigs; - const paths = resolveBundlingPaths(options); const pkgPath = paths.targetPackageJson; const pkg = await fs.readJson(pkgPath); const config = await createConfig(paths, { - ...options, + checksEnabled: options.checksEnabled, isDev: true, baseUrl: url, + frontendConfig, getFrontendAppConfigs: () => { return latestFrontendAppConfigs; }, @@ -49,7 +86,7 @@ export async function serveBundle(options: ServeOptions) { const compiler = webpack(config); - const server = new WebpackDevServer( + server = new WebpackDevServer( { hot: !process.env.CI, devMiddleware: { @@ -73,8 +110,8 @@ export async function serveBundle(options: ServeOptions) { https: url.protocol === 'https:' ? { - cert: options.fullConfig.getString('app.https.certificate.cert'), - key: options.fullConfig.getString('app.https.certificate.key'), + cert: fullConfig.getString('app.https.certificate.cert'), + key: fullConfig.getString('app.https.certificate.key'), } : false, host, @@ -90,7 +127,7 @@ export async function serveBundle(options: ServeOptions) { ); await new Promise((resolve, reject) => { - server.startCallback((err?: Error) => { + server?.startCallback((err?: Error) => { if (err) { reject(err); return; @@ -101,17 +138,10 @@ export async function serveBundle(options: ServeOptions) { }); }); - options.configChannel.port2.onmessage = ({ - data, - }: MessageEvent) => { - latestFrontendAppConfigs = data; - server.invalidate(); - }; - const waitForExit = async () => { for (const signal of ['SIGINT', 'SIGTERM'] as const) { process.on(signal, () => { - server.close(); + server?.close(); // exit instead of resolve. The process is shutting down and resolving a promise here logs an error process.exit(); }); diff --git a/packages/cli/src/lib/bundler/types.ts b/packages/cli/src/lib/bundler/types.ts index 90fff4f3c1..f96e4255f1 100644 --- a/packages/cli/src/lib/bundler/types.ts +++ b/packages/cli/src/lib/bundler/types.ts @@ -29,10 +29,7 @@ export type BundlingOptions = { export type ServeOptions = BundlingPathsOptions & { checksEnabled: boolean; - frontendConfig: Config; - frontendAppConfigs: AppConfig[]; - fullConfig: Config; - configChannel: MessageChannel; + configPaths: string[]; }; export type BuildOptions = BundlingPathsOptions & {