-
Notifications
You must be signed in to change notification settings - Fork 2.2k
/
module-federation-dev-server.impl.ts
124 lines (107 loc) · 3.4 KB
/
module-federation-dev-server.impl.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
import type { Schema } from './schema';
import { ProjectConfiguration, Workspaces } from '@nrwl/devkit';
import { scheduleTarget } from 'nx/src/adapter/ngcli-adapter';
import { BuilderContext, createBuilder } from '@angular-devkit/architect';
import { JsonObject } from '@angular-devkit/core';
import { join } from 'path';
import { executeWebpackServerBuilder } from '../webpack-server/webpack-server.impl';
import { existsSync, readFileSync } from 'fs';
function getDynamicRemotesIfExists(
context: BuilderContext,
p: ProjectConfiguration
) {
// 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,
p.sourceRoot,
'assets/module-federation.manifest.json'
);
if (!existsSync(standardPathToGeneratedMFManifestJson)) {
return [];
}
const moduleFederationManifestJson = readFileSync(
standardPathToGeneratedMFManifestJson,
'utf-8'
);
if (moduleFederationManifestJson) {
// This should have shape of
// {
// "remoteName": "remoteLocation",
// }
const parsedManifest = JSON.parse(moduleFederationManifestJson);
if (
!Object.keys(parsedManifest).every(
(key) =>
typeof key === 'string' && typeof parsedManifest[key] === 'string'
)
) {
return [];
}
return Object.entries(parsedManifest).reduce(
(remotesArray, [remoteName, remoteLocation]) => [
...remotesArray,
[remoteName, remoteLocation],
],
[]
);
}
return [];
}
export function executeModuleFederationDevServerBuilder(
schema: Schema,
context: BuilderContext
) {
const workspaces = new Workspaces(context.workspaceRoot);
const workspaceConfig = workspaces.readWorkspaceConfiguration();
const p = workspaceConfig.projects[context.target.project];
const mfConfigPath = join(
context.workspaceRoot,
p.root,
'module-federation.config.js'
);
let mfeConfig: { remotes: string[] };
try {
mfeConfig = require(mfConfigPath);
} catch {
throw new Error(
`Could not load ${mfConfigPath}. Was this project generated with "@nrwl/angular:host"?`
);
}
const { ...options } = schema;
let unparsedRemotes = mfeConfig.remotes.length > 0 ? mfeConfig.remotes : [];
const dynamicRemotes = getDynamicRemotesIfExists(context, p);
unparsedRemotes = [...unparsedRemotes, ...dynamicRemotes];
const remotes = unparsedRemotes.map((a) => (Array.isArray(a) ? a[0] : a));
const devServeRemotes = !options.devRemotes
? []
: Array.isArray(options.devRemotes)
? options.devRemotes
: [options.devRemotes];
for (const remote of remotes) {
const isDev = devServeRemotes.includes(remote);
const target = isDev ? 'serve' : 'serve-static';
scheduleTarget(
context.workspaceRoot,
{
project: remote,
target,
configuration: context.target.configuration,
runOptions: {},
executor: context.builder.builderName,
},
options.verbose
).then((obs) => {
obs.toPromise().catch((err) => {
throw new Error(
`Remote '${remote}' failed to serve correctly due to the following: \r\n${err.toString()}`
);
});
});
}
return executeWebpackServerBuilder(options, context);
}
export default createBuilder<JsonObject & Schema>(
executeModuleFederationDevServerBuilder
);