Skip to content

Commit 3383707

Browse files
committed
feat: align with angular 15
1 parent 7537a20 commit 3383707

File tree

10 files changed

+116
-46
lines changed

10 files changed

+116
-46
lines changed

libs/mf-runtime/package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
{
22
"name": "@angular-architects/module-federation-runtime",
33
"license": "MIT",
4-
"version": "14.3.14",
4+
"version": "15.0.0",
55
"peerDependencies": {
6-
"@angular/common": ">=14.0.0",
7-
"@angular/core": ">=14.0.0"
6+
"@angular/common": ">=15.0.0",
7+
"@angular/core": ">=15.0.0"
88
},
99
"dependencies": {
1010
"tslib": "^2.0.0"

libs/mf-runtime/src/lib/loader/dynamic-federation.ts

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -164,16 +164,32 @@ export type LoadRemoteModuleManifestOptions = {
164164
};
165165

166166
// eslint-disable-next-line @typescript-eslint/no-explicit-any
167+
export async function loadRemoteModule<T = any>(remoteName: string, exposedModule: string): Promise<T>;
168+
export async function loadRemoteModule<T = any>(options: LoadRemoteModuleOptions): Promise<T>
167169
export async function loadRemoteModule<T = any>(
168-
options: LoadRemoteModuleOptions
170+
optionsOrRemoteName: LoadRemoteModuleOptions | string,
171+
exposedModule?: string
169172
): Promise<T> {
170173
let loadRemoteEntryOptions: LoadRemoteEntryOptions;
171174
let key: string;
172175
let remoteEntry: string;
176+
let options: LoadRemoteModuleOptions;
177+
178+
if (typeof optionsOrRemoteName === 'string') {
179+
options = {
180+
type: 'manifest',
181+
remoteName: optionsOrRemoteName,
182+
exposedModule: exposedModule
183+
}
184+
}
185+
else {
186+
options = optionsOrRemoteName;
187+
}
173188

174189
// To support legacy API (< ng 13)
175190
if (!options.type) {
176-
options.type = 'script';
191+
const hasManifest = Object.keys(config).length > 0;
192+
options.type = hasManifest ? 'manifest' : 'script';
177193
}
178194

179195
if (options.type === 'manifest') {
@@ -230,6 +246,15 @@ export function getManifest<T extends Manifest>(): T {
230246
return config as T;
231247
}
232248

249+
export async function initFederation(manifest: string | ManifestFile, skipRemoteEntries = false): Promise<void> {
250+
if (typeof manifest === 'string') {
251+
return loadManifest(manifest, skipRemoteEntries);
252+
}
253+
else {
254+
return setManifest(manifest, skipRemoteEntries);
255+
}
256+
}
257+
233258
export async function loadManifest(
234259
configFile: string,
235260
skipRemoteEntries = false
@@ -249,7 +274,7 @@ export async function loadManifest(
249274

250275
function parseConfig(config: ManifestFile): Manifest {
251276
const result: Manifest = {};
252-
for (let key in config) {
277+
for (const key in config) {
253278
const value = config[key];
254279

255280
let entry: RemoteConfig;
@@ -273,7 +298,7 @@ function parseConfig(config: ManifestFile): Manifest {
273298
async function loadRemoteEntries() {
274299
const promises: Promise<void>[] = [];
275300

276-
for (let key in config) {
301+
for (const key in config) {
277302
const entry = config[key];
278303

279304
if (entry.type === 'module') {

libs/mf-tools/package.json

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
{
22
"name": "@angular-architects/module-federation-tools",
3-
"version": "14.3.14",
3+
"version": "15.0.0",
44
"license": "MIT",
55
"peerDependencies": {
6-
"@angular/common": ">=14.0.0",
7-
"@angular/core": ">=14.0.0",
8-
"@angular/router": ">=14.0.0",
9-
"@angular-architects/module-federation": "^14.3.14",
10-
"@angular/platform-browser": ">=14.0.0",
6+
"@angular/common": ">=15.0.0",
7+
"@angular/core": ">=15.0.0",
8+
"@angular/router": ">=15.0.0",
9+
"@angular-architects/module-federation": "^15.0.0",
10+
"@angular/platform-browser": ">=15.0.0",
1111
"rxjs": ">= 6.0.0"
1212
},
1313
"dependencies": {

libs/mf/README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ Big thanks to the following people who helped to make this possible:
1212

1313
## Prequisites
1414

15-
- Angular CLI 12 or higher (13, 14)
15+
- Angular CLI 12 or higher (13, 14, 15)
1616

1717
## Motivation 💥
1818

@@ -39,6 +39,7 @@ Since Version 1.2, we also provide some advanced features like:
3939
- Angular 12: @angular-architects/module-federation: ^12.0.0
4040
- Angular 13: @angular-architects/module-federation: ~14.2.0
4141
- Angular 14: @angular-architects/module-federation: ^14.3.0
42+
- Angular 15: @angular-architects/module-federation: ^15.0.0
4243

4344
Beginning with Angular 13, we had to add some changes to adjust to the Angular CLI. Please see the next section for this.
4445

@@ -50,7 +51,7 @@ This library supports `ng update`:
5051
ng update @angular-architects/module-federation
5152
```
5253

53-
If you update by hand (e. g. via `npm install`), make sure you also install a respective version of ngx-build-plus (version 14 for Angular 14, version 13 for Angular 13, etc.)
54+
If you update by hand (e. g. via `npm install`), make sure you also install a respective version of ngx-build-plus (version 15 for Angular 15, version 14 for Angular 14, version 13 for Angular 13, etc.)
5455

5556
## Upgrade from Angular 12 or lower
5657

libs/mf/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@angular-architects/module-federation",
3-
"version": "14.3.14",
3+
"version": "15.0.0",
44
"license": "MIT",
55
"repository": {
66
"type": "GitHub",
@@ -17,7 +17,7 @@
1717
"schematics": "./collection.json",
1818
"builders": "./builders.json",
1919
"dependencies": {
20-
"@angular-architects/module-federation-runtime": "14.3.14",
20+
"@angular-architects/module-federation-runtime": "15.0.0",
2121
"word-wrap": "^1.2.3",
2222
"callsite": "^1.0.0",
2323
"node-fetch": "^2.6.7",

libs/mf/src/schematics/mf/schematic.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -85,9 +85,9 @@ function makeMainAsync(main: string, options: MfSchematicSchema): Rule {
8585

8686
let newMainContent = '';
8787
if (options.type === 'dynamic-host') {
88-
newMainContent = `import { loadManifest } from '@angular-architects/module-federation';
88+
newMainContent = `import { initFederation } from '@angular-architects/module-federation';
8989
90-
loadManifest("/assets/mf.manifest.json")
90+
initFederation('/assets/mf.manifest.json')
9191
.catch(err => console.error(err))
9292
.then(_ => import('./bootstrap'))
9393
.catch(err => console.error(err));
@@ -386,11 +386,11 @@ export default function config(options: MfSchematicSchema): Rule {
386386

387387
const dep = getPackageJsonDependency(tree, 'ngx-build-plus');
388388

389-
if (!dep || !semver.satisfies(dep.version, '>=14.0.0')) {
389+
if (!dep || !semver.satisfies(dep.version, '>=15.0.0')) {
390390
addPackageJsonDependency(tree, {
391391
name: 'ngx-build-plus',
392392
type: NodeDependencyType.Dev,
393-
version: '^14.0.0',
393+
version: '^15.0.0',
394394
overwrite: true,
395395
});
396396

libs/mf/src/server/colors.ts

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -29,22 +29,14 @@ export function print(prefix: string, prefixSize: number, message: string, error
2929
.update(prefix)
3030
.digest("hex");
3131

32-
const color = '#' + correctColor(hash.substring(6,6));
32+
const color = '#' + correctColor(hash.substring(6,12));
3333

3434
prefix = prefix.padEnd(prefixSize);
3535

3636
if (message.endsWith('\n')) {
3737
message = message.substring(0, message.length-1);
3838
}
3939

40-
const color = '#' + correctColor(hash.substr(6, 6));
41-
42-
prefix = prefix.padEnd(prefixSize);
43-
44-
if (message.endsWith('\n')) {
45-
message = message.substr(0, message.length - 1);
46-
}
47-
4840
const coloredPrefix = chalk.hex(color)(prefix) + ' | ';
4941
const lines = message.split('\n');
5042

libs/mf/src/server/workspace.ts

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,14 @@
11
import * as fs from 'fs';
2+
import * as path from 'path';
23

34
export type ProjectType = 'application' | 'library';
45

6+
export interface NxOrCliWorkspaceDef {
7+
projects: {
8+
[name: string]: Project | string;
9+
};
10+
}
11+
512
export interface WorkspaceDef {
613
projects: {
714
[name: string]: Project;
@@ -49,7 +56,25 @@ export function readWorkspaceDef(): WorkspaceDef {
4956
throw new Error('This is not an Angular workspace!');
5057
}
5158
const content = fs.readFileSync(fileName, { encoding: 'utf-8' });
52-
return JSON.parse(content);
59+
const nxOrCliWorspaceDef = JSON.parse(content) as NxOrCliWorkspaceDef;
60+
const worspaceDef = toCliWorkspaceDef(nxOrCliWorspaceDef);
61+
return worspaceDef;
62+
}
63+
64+
function toCliWorkspaceDef(def: NxOrCliWorkspaceDef): WorkspaceDef {
65+
const result: WorkspaceDef = { projects: {} };
66+
for(const key in def.projects) {
67+
const project = def.projects[key];
68+
69+
if (typeof project === 'string') {
70+
const def = path.join(project, 'project.json');
71+
result.projects[key] = loadProjectDef(def);
72+
}
73+
else {
74+
result.projects[key] = project;
75+
}
76+
}
77+
return result;
5378
}
5479

5580
export function readProjectInfos(): ProjectInfo[] {
@@ -67,3 +92,17 @@ export function readProjectInfos(): ProjectInfo[] {
6792
} as ProjectInfo)
6893
);
6994
}
95+
96+
function loadProjectDef(projectDef: string): Project {
97+
try {
98+
const def = JSON.parse(fs.readFileSync(projectDef, 'utf-8'));
99+
if (!def.architect) {
100+
def.architect = def.targets;
101+
}
102+
return def;
103+
}
104+
catch {
105+
throw new Error(`File ${projectDef} not found. Please start this command from your workspace root.`);
106+
}
107+
}
108+

libs/mf/src/utils/share-utils.ts

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -132,9 +132,9 @@ function getSecondaries(
132132
includeSecondaries: IncludeSecondariesOptions,
133133
packagePath: string,
134134
key: string,
135-
shareObject: SharedConfig
135+
shareObject: SharedConfig,
136+
exclude = [...DEFAULT_SECONARIES_SKIP_LIST],
136137
): Record<string, SharedConfig> {
137-
let exclude = [...DEFAULT_SECONARIES_SKIP_LIST];
138138

139139
if (typeof includeSecondaries === 'object') {
140140
if (Array.isArray(includeSecondaries.skip)) {
@@ -192,7 +192,7 @@ function readConfiguredSecondaries(
192192
key != '.' &&
193193
key != './package.json' &&
194194
!key.endsWith('*') &&
195-
exports[key]['default']
195+
(exports[key]['default'] || typeof exports[key] === 'string')
196196
);
197197

198198
const result = {} as Record<string, SharedConfig>;
@@ -216,7 +216,7 @@ function readConfiguredSecondaries(
216216

217217
export function shareAll(
218218
config: CustomSharedConfig = {},
219-
skip: string[] = DEFAULT_SKIP_LIST,
219+
skip: string[] = [...DEFAULT_SKIP_LIST, ...DEFAULT_SECONARIES_SKIP_LIST],
220220
packageJsonPath = ''
221221
): Config {
222222
if (!packageJsonPath) {
@@ -236,14 +236,18 @@ export function shareAll(
236236
share[key] = { ...config };
237237
}
238238

239-
return module.exports.share(share, packageJsonPath);
239+
return module.exports.share(share, packageJsonPath, skip);
240240
}
241241

242242
export function setInferVersion(infer: boolean): void {
243243
inferVersion = infer;
244244
}
245245

246-
export function share(shareObjects: Config, packageJsonPath = ''): Config {
246+
export function share(
247+
shareObjects: Config,
248+
packageJsonPath = '',
249+
skip: string[] = DEFAULT_SECONARIES_SKIP_LIST): Config {
250+
247251
if (!packageJsonPath) {
248252
packageJsonPath = cwd();
249253
}
@@ -283,7 +287,8 @@ export function share(shareObjects: Config, packageJsonPath = ''): Config {
283287
includeSecondaries,
284288
packagePath,
285289
key,
286-
shareObject
290+
shareObject,
291+
skip,
287292
);
288293
addSecondaries(secondaries, result);
289294
}

libs/mf/src/utils/with-mf-plugin.ts

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,25 @@
1-
import { findRootTsConfigJson, shareAll } from './share-utils';
1+
import { DEFAULT_SECONARIES_SKIP_LIST, DEFAULT_SKIP_LIST, findRootTsConfigJson, shareAll } from './share-utils';
22
import { SharedMappings } from './shared-mappings';
33
import { ModifyEntryPlugin } from './modify-entry-plugin';
44

5-
const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin');
5+
import ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin');
66

77
export function withModuleFederationPlugin(config: unknown) {
8-
const sharedMappings = config['sharedMappings'];
8+
const sharedMappings = config['sharedMappings'] || [];
99
delete config['sharedMappings'];
1010

11+
const skip = [
12+
...DEFAULT_SKIP_LIST,
13+
...DEFAULT_SECONARIES_SKIP_LIST,
14+
...(config['skip'] || [])
15+
];
16+
17+
delete config['skip'];
18+
1119
const mappings = new SharedMappings();
12-
mappings.register(findRootTsConfigJson(), sharedMappings);
20+
mappings.register(findRootTsConfigJson(), sharedMappings.filter(m => !skip.includes(m)));
1321

14-
setDefaults(config, mappings);
22+
setDefaults(config, mappings, skip);
1523
const modifyEntryPlugin = createModifyEntryPlugin(config);
1624

1725
const isModule = config['library']?.['type'] === 'module';
@@ -45,7 +53,7 @@ export function withModuleFederationPlugin(config: unknown) {
4553
};
4654
}
4755

48-
function setDefaults(config: unknown, mappings: SharedMappings) {
56+
function setDefaults(config: unknown, mappings: SharedMappings, skip: string[]) {
4957
if (!config['library']) {
5058
config['library'] = {
5159
type: 'module',
@@ -61,7 +69,7 @@ function setDefaults(config: unknown, mappings: SharedMappings) {
6169
singleton: true,
6270
strictVersion: true,
6371
requiredVersion: 'auto',
64-
});
72+
}, skip);
6573
}
6674

6775
if (typeof config['shared'] === 'object') {
@@ -102,7 +110,7 @@ function createModifyEntryPlugin(config: unknown) {
102110
);
103111
}
104112

105-
let modifyEntryConfig = {};
113+
const modifyEntryConfig = {};
106114
let modifyEntryPlugin = null;
107115
if (hasPinned) {
108116
modifyEntryConfig['main'] = { import: pinned };

0 commit comments

Comments
 (0)