1- import * as fs from 'fs' ;
21import * as path from 'path' ;
32import type {
43 EncodedExtension ,
@@ -18,16 +17,13 @@ import {
1817 getSharedModuleMetadata ,
1918} from '../shared-modules/shared-modules-meta' ;
2019import type { DynamicModuleMap } from '../utils/dynamic-module-parser' ;
21- import { getDynamicModuleMap } from '../utils/dynamic-module-parser' ;
2220import { parseJSONC } from '../utils/jsonc' ;
2321import { loadSchema } from '../utils/schema' ;
2422import { ExtensionValidator } from '../validation/ExtensionValidator' ;
2523import { SchemaValidator } from '../validation/SchemaValidator' ;
2624import { ValidationResult } from '../validation/ValidationResult' ;
27- import type { DynamicModuleImportLoaderOptions } from './loaders/dynamic-module-import-loader' ;
28-
29- const dynamicModuleImportLoader =
30- '@openshift-console/dynamic-plugin-sdk-webpack/lib/webpack/loaders/dynamic-module-import-loader' ;
25+ import type { DynamicModulePackageSpecs } from './DynamicModuleImportPlugin' ;
26+ import { DynamicModuleImportPlugin , resolveDynamicModuleMaps } from './DynamicModuleImportPlugin' ;
3127
3228const loadPluginPackageJSON = ( ) => readPkg . sync ( { normalize : false } ) as ConsolePluginPackageJSON ;
3329
@@ -130,7 +126,7 @@ const getDeprecatedSharedModuleWarnings = (pkg: ConsolePluginPackageJSON): strin
130126
131127 if ( deprecated && pluginDeps [ moduleName ] ) {
132128 warnings . push (
133- `shared modules: [DEPRECATION ALERT] ' ${ moduleName } ' is deprecated. ${ deprecated } ` ,
129+ `[DEPRECATION WARNING] Console provided shared module ${ moduleName } has been deprecated: ${ deprecated } ` ,
134130 ) ;
135131 }
136132 } ) ;
@@ -169,24 +165,26 @@ const validateConsoleProvidedSharedModules = (pkg: ConsolePluginPackageJSON) =>
169165/**
170166 * PatternFly packages that support dynamic modules to be used with webpack module federation.
171167 *
172- * Console provided {@link sharedPluginModules} should NOT be listed here.
168+ * Console provided {@link sharedPluginModules} should _NOT_ be listed here.
173169 */
174170const dynamicModulePatternFlyPackages = [
175- '@patternfly/react-charts' ,
176171 '@patternfly/react-core' ,
177172 '@patternfly/react-data-view' ,
178173 '@patternfly/react-icons' ,
179174 '@patternfly/react-table' ,
180175 '@patternfly/react-templates' ,
181176] ;
182177
183- type DynamicModulePackageSpec = Partial < {
184- /** @default 'dist/esm/index.js' */
185- indexModule : string ;
178+ export const dynamicModulePackageSpecs = dynamicModulePatternFlyPackages . reduce <
179+ DynamicModulePackageSpecs
180+ > ( ( acc , moduleName ) => ( { ... acc , [ moduleName ] : { } } ) , { } ) ;
186181
187- /** @default 'module' */
188- resolutionField : string ;
189- } > ;
182+ export const dynamicModuleImportTransformFilter = ( moduleRequest : string ) => {
183+ const isCode = / \. ( j s x ? | t s x ? ) $ / . test ( moduleRequest ) ;
184+ const isVendor = moduleRequest . includes ( '/node_modules/' ) ;
185+
186+ return isCode && ( ! isVendor || moduleRequest . includes ( '/node_modules/@openshift-console/' ) ) ;
187+ } ;
190188
191189export type ConsoleRemotePluginOptions = Partial < {
192190 /**
@@ -250,9 +248,9 @@ export type ConsoleRemotePluginOptions = Partial<{
250248 /**
251249 * Some vendor packages may support dynamic modules to be used with webpack module federation.
252250 *
253- * If a module request matches the `transformImports` filter, that module will have its imports
254- * transformed so that any _index_ imports for given vendor packages become imports for specific
255- * dynamic modules of these vendor packages.
251+ * If a module request matches the `moduleFilter`, code of that module will be modified so that
252+ * any _index_ imports for given vendor packages become imports for specific dynamic modules of
253+ * these vendor packages.
256254 *
257255 * For example, the following import:
258256 * ```ts
@@ -268,11 +266,23 @@ export type ConsoleRemotePluginOptions = Partial<{
268266 * Each dynamic module (such as `@patternfly/react-core/dist/dynamic/components/Alert`) will
269267 * be treated as a separate shared module at runtime. This approach allows for more efficient
270268 * federation of vendor package code, as opposed to sharing the whole vendor package index
271- * (such as `@patternfly/react-core`) that pulls in all of its code.
269+ * (such as `@patternfly/react-core`) that would cause all of its code to be pulled into the
270+ * Console compilation and inflate the vendor bundle size.
272271 */
273272 sharedDynamicModuleSettings : Partial < {
274273 /**
275- * Paths to `node_modules` directories to search when parsing dynamic modules.
274+ * Packages that support dynamic modules for use with webpack module federation.
275+ *
276+ * Each vendor package listed here should include a `dist/dynamic` directory containing
277+ * `package.json` files representing parts of that package to be shared separately between
278+ * the Console application and its plugins at runtime.
279+ *
280+ * If not specified, use a default list of PatternFly packages that support dynamic modules.
281+ */
282+ packageSpecs : DynamicModulePackageSpecs ;
283+
284+ /**
285+ * Paths to `node_modules` directories to search when resolving dynamic modules.
276286 *
277287 * Paths listed here _must_ be absolute.
278288 *
@@ -284,33 +294,22 @@ export type ConsoleRemotePluginOptions = Partial<{
284294 modulePaths : string [ ] ;
285295
286296 /**
287- * Attempt to parse dynamic modules for these packages.
288- *
289- * Each package listed here should include a `dist/dynamic` directory containing `package.json`
290- * files that refer to specific modules of that package.
291- *
292- * If not specified, use packages listed in {@link dynamicModulePatternFlyPackages} with default
293- * settings.
294- */
295- packageSpecs : Record < string , DynamicModulePackageSpec > ;
296-
297- /**
298- * Import transformations will be applied to modules that match this filter.
297+ * Modules that match this filter will have their imports transformed.
299298 *
300299 * If not specified, the following conditions must be all true for a module to be matched:
301- * - request ends with one of `.js`, `.jsx`, `.ts`, `.tsx`
300+ * - request ends with `.js`, `.jsx`, `.ts` or `.tsx`
302301 * - request does not contain `node_modules` path elements (i.e. not a vendor module request),
303302 * _except_ for `@openshift-console/*` packages
304303 */
305- transformImports : ( moduleRequest : string ) => boolean ;
304+ moduleFilter : ( moduleRequest : string ) => boolean ;
306305 } > ;
307306} > ;
308307
309308/**
310309 * Generates Console dynamic plugin remote container and related assets.
311310 *
312- * Refer to `frontend/packages/ console-dynamic-plugin-sdk/src/shared-modules.ts` for details on
313- * Console application vs. dynamic plugins shared module configuration.
311+ * Refer to `console-dynamic-plugin-sdk/src/shared-modules.ts` for details on Console provided
312+ * shared modules and their configuration.
314313 *
315314 * @see {@link sharedPluginModules }
316315 * @see {@link getSharedModuleMetadata }
@@ -342,6 +341,8 @@ export class ConsoleRemotePlugin implements WebpackPluginInstance {
342341 validateConsoleProvidedSharedModules ( this . pkg ) . report ( ) ;
343342 }
344343
344+ validateConsoleBuildMetadata ( this . adaptedOptions . pluginMetadata ) . report ( ) ;
345+
345346 const overlapDependencyNames = _ . intersection (
346347 Object . keys ( this . adaptedOptions . pluginMetadata . dependencies ?? { } ) ,
347348 Object . keys ( this . adaptedOptions . pluginMetadata . optionalDependencies ?? { } ) ,
@@ -359,24 +360,10 @@ export class ConsoleRemotePlugin implements WebpackPluginInstance {
359360 path . resolve ( process . cwd ( ) , 'node_modules' ) ,
360361 ] ;
361362
362- const sharedDynamicModulePackageSpecs =
363- this . adaptedOptions . sharedDynamicModuleSettings . packageSpecs ??
364- dynamicModulePatternFlyPackages . reduce < Record < string , DynamicModulePackageSpec > > (
365- ( acc , moduleName ) => ( { ...acc , [ moduleName ] : { } } ) ,
366- { } ,
367- ) ;
368-
369- this . sharedDynamicModuleMaps = Object . entries ( sharedDynamicModulePackageSpecs ) . reduce <
370- Record < string , DynamicModuleMap >
371- > ( ( acc , [ pkgName , { indexModule = 'dist/esm/index.js' , resolutionField = 'module' } ] ) => {
372- const basePath = resolvedModulePaths
373- . map ( ( p ) => path . resolve ( p , pkgName ) )
374- . find ( ( p ) => fs . existsSync ( p ) && fs . statSync ( p ) . isDirectory ( ) ) ;
375-
376- return basePath
377- ? { ...acc , [ pkgName ] : getDynamicModuleMap ( basePath , indexModule , resolutionField ) }
378- : acc ;
379- } , { } ) ;
363+ this . sharedDynamicModuleMaps = resolveDynamicModuleMaps (
364+ this . adaptedOptions . sharedDynamicModuleSettings . packageSpecs ?? dynamicModulePackageSpecs ,
365+ resolvedModulePaths ,
366+ ) ;
380367 }
381368
382369 apply ( compiler : Compiler ) {
@@ -401,6 +388,8 @@ export class ConsoleRemotePlugin implements WebpackPluginInstance {
401388
402389 const logger = compiler . getInfrastructureLogger ( ConsoleRemotePlugin . name ) ;
403390
391+ // Dynamic plugin assets should be loaded from /api/plugins/<plugin-name> endpoint.
392+ // Console Bridge server will fetch the asset from the appropriate plugin web server.
404393 const publicPath = `/api/plugins/${ name } /` ;
405394
406395 if ( compiler . options . output . publicPath !== undefined ) {
@@ -454,10 +443,14 @@ export class ConsoleRemotePlugin implements WebpackPluginInstance {
454443 : 'plugin-entry.js' ,
455444 } ) . apply ( compiler ) ;
456445
457- validateConsoleBuildMetadata ( pluginMetadata ) . report ( ) ;
446+ new DynamicModuleImportPlugin ( {
447+ dynamicModuleMaps : this . sharedDynamicModuleMaps ,
448+ moduleFilter : sharedDynamicModuleSettings . moduleFilter ?? dynamicModuleImportTransformFilter ,
449+ } ) . apply ( compiler ) ;
458450
459- if ( validateExtensionIntegrity ) {
460- compiler . hooks . emit . tap ( ConsoleRemotePlugin . name , ( compilation ) => {
451+ // Post-build validations performed before emitting assets
452+ compiler . hooks . emit . tap ( ConsoleRemotePlugin . name , ( compilation ) => {
453+ if ( validateExtensionIntegrity ) {
461454 const result = new ExtensionValidator ( 'Console plugin extensions' ) . validate (
462455 compilation ,
463456 extensions ,
@@ -471,49 +464,11 @@ export class ConsoleRemotePlugin implements WebpackPluginInstance {
471464 error . file = extensionsFile ;
472465 compilation . errors . push ( error ) ;
473466 }
474- } ) ;
475- }
476-
477- const transformImports =
478- sharedDynamicModuleSettings . transformImports ??
479- ( ( moduleRequest ) => {
480- const isCode = / \. ( j s x ? | t s x ? ) $ / . test ( moduleRequest ) ;
481- const isVendor = moduleRequest . includes ( '/node_modules/' ) ;
482-
483- return isCode && ( ! isVendor || moduleRequest . includes ( '/node_modules/@openshift-console/' ) ) ;
484- } ) ;
467+ }
485468
486- compiler . hooks . thisCompilation . tap ( ConsoleRemotePlugin . name , ( compilation ) => {
487469 getDeprecatedSharedModuleWarnings ( this . pkg ) . forEach ( ( message ) => {
488470 compilation . warnings . push ( new compiler . webpack . WebpackError ( message ) ) ;
489471 } ) ;
490-
491- const modifiedModules : string [ ] = [ ] ;
492-
493- compiler . webpack . NormalModule . getCompilationHooks ( compilation ) . beforeLoaders . tap (
494- ConsoleRemotePlugin . name ,
495- ( loaders , normalModule ) => {
496- const { userRequest } = normalModule ;
497-
498- const moduleRequest = userRequest . substring (
499- userRequest . lastIndexOf ( '!' ) === - 1 ? 0 : userRequest . lastIndexOf ( '!' ) + 1 ,
500- ) ;
501-
502- if ( ! modifiedModules . includes ( moduleRequest ) && transformImports ( moduleRequest ) ) {
503- const loaderOptions : DynamicModuleImportLoaderOptions = {
504- dynamicModuleMaps : this . sharedDynamicModuleMaps ,
505- resourceMetadata : { jsx : / \. ( j s x | t s x ) $ / . test ( moduleRequest ) } ,
506- } ;
507-
508- normalModule . loaders . push ( {
509- loader : dynamicModuleImportLoader ,
510- options : loaderOptions ,
511- } as any ) ;
512-
513- modifiedModules . push ( moduleRequest ) ;
514- }
515- } ,
516- ) ;
517472 } ) ;
518473 }
519474}
0 commit comments