Skip to content

Commit e7eb403

Browse files
committed
merge
2 parents 94339c5 + 8c9201b commit e7eb403

File tree

2 files changed

+66
-16
lines changed

2 files changed

+66
-16
lines changed
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Migration Guide: Module Federation to Native Federation for Angular
2+
3+
## Motivation
4+
5+
Since Angular 17, the CLI ships with an esbuild-based builder that is remarkable faster than the original webpack-based solution. This new builder is used for newly generated projects and beginning with Angular 18 ng updates also migrates existing projects.
6+
7+
Native Federation for Angular is a thin wrapper around the esbuild builder that allows to use the proven mental model of Module Federation.
8+
9+
## Prerequisites
10+
11+
- Update your solution to the newest Angular and CLI version
12+
- Update your solution to the newest version of `@angular-architects/module-federation`
13+
- Have a look to our [FAQs about sharing packages with Native Federation](share-faq.md)
14+
15+
## Migration for Angular CLI projects
16+
17+
## Migration for Nx projects
18+
19+
## Issues
20+
21+
We have tested this guide with several projects. However, e

libs/native-federation/src/schematics/init/schematic.ts

Lines changed: 45 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ type NormalizedOptions = {
3232
projectRoot: string;
3333
projectSourceRoot: string;
3434
manifestPath: string;
35+
manifestRelPath: string;
3536
projectConfig: any;
3637
main: string;
3738
port: number;
@@ -70,14 +71,15 @@ export default function config(options: MfSchematicSchema): Rule {
7071
const workspaceFileName = getWorkspaceFileName(tree);
7172
const workspace = JSON.parse(tree.read(workspaceFileName).toString('utf8'));
7273

73-
const normalized = normalizeOptions(options, workspace);
74+
const normalized = normalizeOptions(options, workspace, tree);
7475

7576
const {
7677
polyfills,
7778
projectName,
7879
projectRoot,
7980
projectSourceRoot,
8081
manifestPath,
82+
manifestRelPath,
8183
main,
8284
} = normalized;
8385

@@ -116,22 +118,30 @@ export default function config(options: MfSchematicSchema): Rule {
116118

117119
context.addTask(new NodePackageInstallTask());
118120

119-
return chain([generateRule, makeMainAsync(main, options, remoteMap)]);
121+
return chain([
122+
generateRule,
123+
makeMainAsync(main, options, remoteMap, manifestRelPath),
124+
]);
120125
};
121126
}
122127

123-
export function patchAngularBuild(tree) {
128+
export function patchAngularBuild(tree: Tree) {
124129
const packagePath = 'node_modules/@angular/build/package.json';
125130
const privatePath = 'node_modules/@angular/build/private.js';
126131

127132
if (!tree.exists(packagePath)) {
128133
return;
129134
}
130135

131-
const packageJson = JSON.parse(tree.read(packagePath));
136+
const packageJson = JSON.parse(tree.read(packagePath).toString('utf8'));
132137
patchAngularBuildPackageJson(packageJson);
133138
tree.overwrite(packagePath, JSON.stringify(packageJson, null, 2));
134-
tree.overwrite(privatePath, privateEntrySrc);
139+
140+
if (!tree.exists(privatePath)) {
141+
tree.create(privatePath, privateEntrySrc);
142+
} else {
143+
tree.overwrite(privatePath, privateEntrySrc);
144+
}
135145
}
136146

137147
function updateWorkspaceConfig(
@@ -159,18 +169,14 @@ function updateWorkspaceConfig(
159169
delete originalBuild.configurations?.development?.vendorChunk;
160170
}
161171

162-
// if (originalBuild.options.browser) {
163-
// const browser = originalBuild.options.browser;
164-
// delete originalBuild.options.browser;
165-
// originalBuild.options.main = browser;
166-
// }
167-
168172
if (originalBuild.options.main) {
169173
const main = originalBuild.options.main;
170174
delete originalBuild.options.main;
171175
originalBuild.options.browser = main;
172176
}
173177

178+
delete originalBuild.options.commonChunk;
179+
174180
projectConfig.architect.esbuild = originalBuild;
175181

176182
projectConfig.architect.build = {
@@ -192,6 +198,8 @@ function updateWorkspaceConfig(
192198
serve.options ??= {};
193199
serve.options.port = port;
194200

201+
delete serve.options.commonChunk;
202+
195203
const serveProd = projectConfig.architect.serve.configurations?.production;
196204
if (serveProd) {
197205
serveProd.buildTarget = `${projectName}:esbuild:production`;
@@ -232,7 +240,8 @@ function updateWorkspaceConfig(
232240

233241
function normalizeOptions(
234242
options: MfSchematicSchema,
235-
workspace: any
243+
workspace: any,
244+
tree: Tree
236245
): NormalizedOptions {
237246
if (!options.project) {
238247
options.project = workspace.defaultProject;
@@ -266,10 +275,22 @@ function normalizeOptions(
266275
'/'
267276
);
268277

269-
const manifestPath = path
270-
.join(projectRoot, 'public/federation.manifest.json')
278+
const publicPath = path.join(projectRoot, 'public').replace(/\\/g, '/');
279+
280+
let manifestPath = path
281+
.join(publicPath, 'federation.manifest.json')
271282
.replace(/\\/g, '/');
272283

284+
let manifestRelPath = 'public/federation.manifest.json';
285+
286+
if (!tree.exists(publicPath)) {
287+
manifestPath = path
288+
.join(projectRoot, 'src/assets/federation.manifest.json')
289+
.replace(/\\/g, '/');
290+
291+
manifestRelPath = 'assets/federation.manifest.json';
292+
}
293+
273294
const main =
274295
projectConfig.architect.build.options.main ||
275296
projectConfig.architect.build.options.browser;
@@ -278,13 +299,20 @@ function normalizeOptions(
278299
projectConfig.architect.build.options.polyfills = [];
279300
}
280301

302+
if (typeof projectConfig.architect.build.options.polyfills === 'string') {
303+
projectConfig.architect.build.options.polyfills = [
304+
projectConfig.architect.build.options.polyfills,
305+
];
306+
}
307+
281308
const polyfills = projectConfig.architect.build.options.polyfills;
282309
return {
283310
polyfills,
284311
projectName,
285312
projectRoot,
286313
projectSourceRoot,
287314
manifestPath,
315+
manifestRelPath,
288316
projectConfig,
289317
main,
290318
port: +(options.port || 4200),
@@ -348,7 +376,8 @@ function generateRemoteMap(workspace: any, projectName: string) {
348376
function makeMainAsync(
349377
main: string,
350378
options: MfSchematicSchema,
351-
remoteMap: unknown
379+
remoteMap: unknown,
380+
manifestRelPath: string
352381
): Rule {
353382
return async function (tree) {
354383
const mainPath = path.dirname(main);
@@ -366,7 +395,7 @@ function makeMainAsync(
366395
if (options.type === 'dynamic-host') {
367396
newMainContent = `import { initFederation } from '@angular-architects/native-federation';
368397
369-
initFederation('federation.manifest.json')
398+
initFederation('${manifestRelPath}')
370399
.catch(err => console.error(err))
371400
.then(_ => import('./bootstrap'))
372401
.catch(err => console.error(err));

0 commit comments

Comments
 (0)