feat(angular): add option for custom path to manifest file (#15053)

Co-authored-by: Leosvel Pérez Espinosa <leosvel.perez.espinosa@gmail.com>
This commit is contained in:
Colum Ferry 2023-02-16 16:12:20 +00:00 committed by GitHub
parent 3eeb4a3e4d
commit f913b905a1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 82 additions and 13 deletions

View File

@ -108,6 +108,10 @@
"type": "array",
"items": { "type": "string" },
"description": "List of remote applications to not automatically serve, either statically or in development mode. This can be useful for multi-repository module federation setups where the host application uses a remote application from an external repository."
},
"pathToManifestFile": {
"type": "string",
"description": "Path to a Module Federation manifest file (e.g. `my/path/to/module-federation.manifest.json`) containing the dynamic remote applications relative to the workspace root."
}
},
"additionalProperties": false,

View File

@ -77,6 +77,10 @@
"verbose": {
"type": "boolean",
"description": "Adds more details to output logging."
},
"pathToManifestFile": {
"type": "string",
"description": "Path to a Module Federation manifest file (e.g. `my/path/to/module-federation.manifest.json`) containing the dynamic remote applications relative to the workspace root."
}
},
"additionalProperties": false,

View File

@ -12,6 +12,8 @@ import {
getStaticRemotes,
validateDevRemotes,
} from '../utilities/module-federation';
import { existsSync } from 'fs';
import { extname, join } from 'path';
export function executeModuleFederationDevServerBuilder(
schema: Schema,
@ -24,6 +26,29 @@ export function executeModuleFederationDevServerBuilder(
const ws = new Workspaces(workspaceRoot);
const project = workspaceProjects[context.target.project];
let pathToManifestFile = join(
context.workspaceRoot,
project.sourceRoot,
'assets/module-federation.manifest.json'
);
if (options.pathToManifestFile) {
const userPathToManifestFile = join(
context.workspaceRoot,
options.pathToManifestFile
);
if (!existsSync(userPathToManifestFile)) {
throw new Error(
`The provided Module Federation manifest file path does not exist. Please check the file exists at "${userPathToManifestFile}".`
);
} else if (extname(options.pathToManifestFile) !== '.json') {
throw new Error(
`The Module Federation manifest file must be a JSON. Please ensure the file at ${userPathToManifestFile} is a JSON.`
);
}
pathToManifestFile = userPathToManifestFile;
}
validateDevRemotes(options, workspaceProjects);
const remotesToSkip = new Set(options.skipRemotes ?? []);
@ -37,7 +62,8 @@ export function executeModuleFederationDevServerBuilder(
project,
context,
workspaceProjects,
remotesToSkip
remotesToSkip,
pathToManifestFile
);
const remotes = [...staticRemotes, ...dynamicRemotes];

View File

@ -19,4 +19,5 @@ export interface Schema {
poll?: number;
devRemotes?: string[];
skipRemotes?: string[];
pathToManifestFile?: string;
}

View File

@ -118,6 +118,10 @@
"type": "string"
},
"description": "List of remote applications to not automatically serve, either statically or in development mode. This can be useful for multi-repository module federation setups where the host application uses a remote application from an external repository."
},
"pathToManifestFile": {
"type": "string",
"description": "Path to a Module Federation manifest file (e.g. `my/path/to/module-federation.manifest.json`) containing the dynamic remote applications relative to the workspace root."
}
},
"additionalProperties": false,

View File

@ -12,9 +12,10 @@ import {
} from '../utilities/module-federation';
import { switchMap, tap } from 'rxjs/operators';
import { from } from 'rxjs';
import { join } from 'path';
import { extname, join } from 'path';
import { execSync, fork } from 'child_process';
import { scheduleTarget } from 'nx/src/adapter/ngcli-adapter';
import { existsSync } from 'fs';
export function executeModuleFederationDevSSRBuilder(
schema: Schema,
@ -27,6 +28,29 @@ export function executeModuleFederationDevSSRBuilder(
const ws = new Workspaces(workspaceRoot);
const project = workspaceProjects[context.target.project];
let pathToManifestFile = join(
context.workspaceRoot,
project.sourceRoot,
'assets/module-federation.manifest.json'
);
if (options.pathToManifestFile) {
const userPathToManifestFile = join(
context.workspaceRoot,
options.pathToManifestFile
);
if (!existsSync(userPathToManifestFile)) {
throw new Error(
`The provided Module Federation manifest file path does not exist. Please check the file exists at "${userPathToManifestFile}".`
);
} else if (extname(options.pathToManifestFile) !== '.json') {
throw new Error(
`The Module Federation manifest file must be a JSON. Please ensure the file at ${userPathToManifestFile} is a JSON.`
);
}
pathToManifestFile = userPathToManifestFile;
}
validateDevRemotes(options, workspaceProjects);
const remotesToSkip = new Set(options.skipRemotes ?? []);
@ -40,7 +64,8 @@ export function executeModuleFederationDevSSRBuilder(
project,
context,
workspaceProjects,
remotesToSkip
remotesToSkip,
pathToManifestFile
);
const remotes = [...staticRemotes, ...dynamicRemotes];

View File

@ -13,4 +13,5 @@ export interface Schema {
devRemotes?: string[];
skipRemotes?: string[];
verbose?: boolean;
pathToManifestFile?: string;
}

View File

@ -78,6 +78,10 @@
"verbose": {
"type": "boolean",
"description": "Adds more details to output logging."
},
"pathToManifestFile": {
"type": "string",
"description": "Path to a Module Federation manifest file (e.g. `my/path/to/module-federation.manifest.json`) containing the dynamic remote applications relative to the workspace root."
}
},
"additionalProperties": false,

View File

@ -7,23 +7,23 @@ export function getDynamicRemotes(
project: ProjectConfiguration,
context: import('@angular-devkit/architect').BuilderContext,
workspaceProjects: Record<string, ProjectConfiguration>,
remotesToSkip: Set<string>
remotesToSkip: Set<string>,
pathToManifestFile = join(
context.workspaceRoot,
project.sourceRoot,
'assets/module-federation.manifest.json'
)
): string[] {
// check for dynamic remotes
// we should only check for dynamic based on what we generate
// and fallback to empty array
const standardPathToGeneratedMFManifestJson = join(
context.workspaceRoot,
project.sourceRoot,
'assets/module-federation.manifest.json'
);
if (!existsSync(standardPathToGeneratedMFManifestJson)) {
if (!existsSync(pathToManifestFile)) {
return [];
}
const moduleFederationManifestJson = readFileSync(
standardPathToGeneratedMFManifestJson,
pathToManifestFile,
'utf-8'
);
@ -54,8 +54,8 @@ export function getDynamicRemotes(
if (invalidDynamicRemotes.length) {
throw new Error(
invalidDynamicRemotes.length === 1
? `Invalid dynamic remote configured in "${standardPathToGeneratedMFManifestJson}": ${invalidDynamicRemotes[0]}.`
: `Invalid dynamic remotes configured in "${standardPathToGeneratedMFManifestJson}": ${invalidDynamicRemotes.join(
? `Invalid dynamic remote configured in "${pathToManifestFile}": ${invalidDynamicRemotes[0]}.`
: `Invalid dynamic remotes configured in "${pathToManifestFile}": ${invalidDynamicRemotes.join(
', '
)}.`
);