From 0727db405587b43542818e3493829fb787b65c9e Mon Sep 17 00:00:00 2001 From: Vojtech Szocs Date: Thu, 20 Jun 2024 16:50:42 +0000 Subject: [PATCH 1/2] Improve control over PatternFly shared modules used in Console plugins --- .../src/webpack/ConsoleRemotePlugin.ts | 61 +++++++++++++++---- 1 file changed, 50 insertions(+), 11 deletions(-) diff --git a/frontend/packages/console-dynamic-plugin-sdk/src/webpack/ConsoleRemotePlugin.ts b/frontend/packages/console-dynamic-plugin-sdk/src/webpack/ConsoleRemotePlugin.ts index d87d2010f1e..5ae1b05469c 100644 --- a/frontend/packages/console-dynamic-plugin-sdk/src/webpack/ConsoleRemotePlugin.ts +++ b/frontend/packages/console-dynamic-plugin-sdk/src/webpack/ConsoleRemotePlugin.ts @@ -1,3 +1,4 @@ +import * as fs from 'fs'; import * as path from 'path'; import { DynamicRemotePlugin, @@ -50,11 +51,21 @@ const getPackageDependencies = (pkg: readPkg.PackageJson) => ({ const getPluginSDKPackageDependencies = () => loadVendorPackageJSON('@openshift-console/dynamic-plugin-sdk').dependencies; +const getPatternFlyMajorVersion = (pkg: ConsolePluginPackageJSON) => { + const pluginDeps = getPackageDependencies(pkg); + const pfCoreVersionRange = pluginDeps['@patternfly/react-core']; + + return semver.validRange(pfCoreVersionRange) + ? semver.minVersion(pfCoreVersionRange)?.major + : undefined; +}; + const getPatternFlyStyles = (baseDir: string) => glob.sync(`${baseDir}/node_modules/@patternfly/react-styles/**/*.css`); // https://webpack.js.org/plugins/module-federation-plugin/#sharing-hints -const getWebpackSharedModules = () => { +const getWebpackSharedModules = (pkg: ConsolePluginPackageJSON) => { + const pfMajorVersion = getPatternFlyMajorVersion(pkg); const sdkPkgDeps = getPluginSDKPackageDependencies(); return sharedPluginModules.reduce((acc, moduleName) => { @@ -62,6 +73,13 @@ const getWebpackSharedModules = () => { const providedVersionRange = sdkPkgDeps[moduleName]; const moduleConfig: WebpackSharedConfig = { singleton }; + // Console provides PatternFly 4 shared modules to its plugins for backwards compatibility. + // Plugins using PatternFly 5 and higher share the PatternFly code bits via dynamic modules. + // TODO(vojtech): remove this code when Console drops support for PatternFly 4 + if (moduleName.startsWith('@patternfly/') && pfMajorVersion > 4) { + return acc; + } + if (!allowFallback) { moduleConfig.import = false; } @@ -229,6 +247,18 @@ export type ConsoleRemotePluginOptions = Partial<{ * (such as `@patternfly/react-core`) that pulls in all of its code. */ sharedDynamicModuleSettings: Partial<{ + /** + * Paths to `node_modules` directories to search when parsing dynamic modules. + * + * Paths listed here _must_ be absolute. + * + * If not specified, the list will contain a single entry: + * ```ts + * path.resolve(process.cwd(), 'node_modules') + * ``` + */ + modulePaths: string[]; + /** * Attempt to parse dynamic modules for these packages. * @@ -299,6 +329,10 @@ export class ConsoleRemotePlugin implements webpack.WebpackPluginInstance { validateConsoleProvidedSharedModules(this.pkg).report(); } + const resolvedModulePaths = this.adaptedOptions.sharedDynamicModuleSettings.modulePaths ?? [ + path.resolve(process.cwd(), 'node_modules'), + ]; + this.sharedDynamicModuleMaps = Object.entries( this.adaptedOptions.sharedDynamicModuleSettings.packageSpecs ?? { '@patternfly/react-core': {}, @@ -306,14 +340,17 @@ export class ConsoleRemotePlugin implements webpack.WebpackPluginInstance { '@patternfly/react-table': {}, }, ).reduce>( - (acc, [pkgName, { indexModule = 'dist/esm/index.js', resolutionField = 'module' }]) => ({ - ...acc, - [pkgName]: getDynamicModuleMap( - path.resolve(this.baseDir, 'node_modules', pkgName), - indexModule, - resolutionField, - ), - }), + (acc, [pkgName, { indexModule = 'dist/esm/index.js', resolutionField = 'module' }]) => { + const basePath = resolvedModulePaths + .map((p) => path.resolve(p, pkgName)) + .find((p) => fs.existsSync(p) && fs.statSync(p).isDirectory()); + + if (basePath) { + acc[pkgName] = getDynamicModuleMap(basePath, indexModule, resolutionField); + } + + return acc; + }, {}, ); } @@ -358,7 +395,9 @@ export class ConsoleRemotePlugin implements webpack.WebpackPluginInstance { } }); - const allSharedDynamicModules = Object.entries(this.sharedDynamicModuleMaps).reduce< + const consoleProvidedSharedModules = getWebpackSharedModules(this.pkg); + + const sharedDynamicModules = Object.entries(this.sharedDynamicModuleMaps).reduce< WebpackSharedObject >( (acc, [moduleName, dynamicModuleMap]) => ({ @@ -379,7 +418,7 @@ export class ConsoleRemotePlugin implements webpack.WebpackPluginInstance { exposedModules, }, extensions, - sharedModules: { ...getWebpackSharedModules(), ...allSharedDynamicModules }, + sharedModules: { ...consoleProvidedSharedModules, ...sharedDynamicModules }, entryCallbackSettings: { name: 'loadPluginEntry', pluginID: `${name}@${version}`, From 9505f4cc7954cc09e60c4716089e9e85c8ae19d4 Mon Sep 17 00:00:00 2001 From: Vojtech Szocs Date: Mon, 24 Jun 2024 15:57:08 +0000 Subject: [PATCH 2/2] Address review comments --- .../src/webpack/ConsoleRemotePlugin.ts | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/frontend/packages/console-dynamic-plugin-sdk/src/webpack/ConsoleRemotePlugin.ts b/frontend/packages/console-dynamic-plugin-sdk/src/webpack/ConsoleRemotePlugin.ts index 5ae1b05469c..fcf521be99b 100644 --- a/frontend/packages/console-dynamic-plugin-sdk/src/webpack/ConsoleRemotePlugin.ts +++ b/frontend/packages/console-dynamic-plugin-sdk/src/webpack/ConsoleRemotePlugin.ts @@ -345,11 +345,9 @@ export class ConsoleRemotePlugin implements webpack.WebpackPluginInstance { .map((p) => path.resolve(p, pkgName)) .find((p) => fs.existsSync(p) && fs.statSync(p).isDirectory()); - if (basePath) { - acc[pkgName] = getDynamicModuleMap(basePath, indexModule, resolutionField); - } - - return acc; + return basePath + ? { ...acc, [pkgName]: getDynamicModuleMap(basePath, indexModule, resolutionField) } + : acc; }, {}, );