feat(angular): replace mfe references with mf (#10957)

This commit is contained in:
Colum Ferry 2022-07-01 14:48:38 +01:00 committed by GitHub
parent 778f13fdaf
commit 37072bc5d6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
58 changed files with 592 additions and 212 deletions

View File

@ -196,13 +196,13 @@
"description": "Split the project configuration into `<projectRoot>/project.json` rather than including it inside `workspace.json`.", "description": "Split the project configuration into `<projectRoot>/project.json` rather than including it inside `workspace.json`.",
"type": "boolean" "type": "boolean"
}, },
"mfe": { "mf": {
"description": "Generate a Module Federation configuration for the application", "description": "Generate a Module Federation configuration for the application",
"type": "boolean", "type": "boolean",
"default": false, "default": false,
"x-deprecated": "Use the `host` or `remote` generators instead. Support for generating Module Federation applications using the application generator will be removed in an upcoming version." "x-deprecated": "Use the `host` or `remote` generators instead. Support for generating Module Federation applications using the application generator will be removed in an upcoming version."
}, },
"mfeType": { "mfType": {
"type": "string", "type": "string",
"enum": ["host", "remote"], "enum": ["host", "remote"],
"description": "Type of application to generate the Module Federation configuration for.", "description": "Type of application to generate the Module Federation configuration for.",
@ -1732,11 +1732,11 @@
"path": "/packages/angular/src/generators/scam-pipe/schema.json" "path": "/packages/angular/src/generators/scam-pipe/schema.json"
}, },
{ {
"name": "setup-mfe", "name": "setup-mf",
"factory": "./src/generators/setup-mfe/setup-mfe", "factory": "./src/generators/setup-mf/setup-mf",
"schema": { "schema": {
"$schema": "http://json-schema.org/schema", "$schema": "http://json-schema.org/schema",
"$id": "GeneratorAngularMFESetup", "$id": "GeneratorAngularMFSetup",
"cli": "nx", "cli": "nx",
"title": "Generate Module Federation Setup for Angular App", "title": "Generate Module Federation Setup for Angular App",
"description": "Create Module Federation configuration files for given Angular Application.", "description": "Create Module Federation configuration files for given Angular Application.",
@ -1748,7 +1748,7 @@
"$default": { "$source": "argv", "index": 0 }, "$default": { "$source": "argv", "index": 0 },
"x-prompt": "What app would you like to generate a Module Federation configuration for?" "x-prompt": "What app would you like to generate a Module Federation configuration for?"
}, },
"mfeType": { "mfType": {
"type": "string", "type": "string",
"enum": ["host", "remote"], "enum": ["host", "remote"],
"description": "Type of application to generate the Module Federation configuration for.", "description": "Type of application to generate the Module Federation configuration for.",
@ -1794,15 +1794,15 @@
"description": "The prefix to use for any generated component." "description": "The prefix to use for any generated component."
} }
}, },
"required": ["appName", "mfeType"], "required": ["appName", "mfType"],
"additionalProperties": false, "additionalProperties": false,
"presets": [] "presets": []
}, },
"description": "Generate a Module Federation configuration for a given Angular application.", "description": "Generate a Module Federation configuration for a given Angular application.",
"implementation": "/packages/angular/src/generators/setup-mfe/setup-mfe.ts", "implementation": "/packages/angular/src/generators/setup-mf/setup-mf.ts",
"aliases": [], "aliases": [],
"hidden": false, "hidden": false,
"path": "/packages/angular/src/generators/setup-mfe/schema.json" "path": "/packages/angular/src/generators/setup-mf/schema.json"
}, },
{ {
"name": "setup-tailwind", "name": "setup-tailwind",

View File

@ -39,7 +39,7 @@
"scam", "scam",
"scam-directive", "scam-directive",
"scam-pipe", "scam-pipe",
"setup-mfe", "setup-mf",
"setup-tailwind", "setup-tailwind",
"stories", "stories",
"storybook-configuration", "storybook-configuration",

View File

@ -34,12 +34,12 @@ To start with, we need to create a new Nx Workspace. We can do this easily with:
```bash ```bash
# Npm # Npm
npx create-nx-workspace ng-mfe npx create-nx-workspace ng-mf
``` ```
```bash ```bash
# Yarn # Yarn
yarn create nx-workspace ng-mfe --packageManager=yarn yarn create nx-workspace ng-mf --packageManager=yarn
``` ```
You'll be prompted for a preset. We recommend selecting `empty` as it will allow you finer control over your workspace configuration. You'll be prompted for a preset. We recommend selecting `empty` as it will allow you finer control over your workspace configuration.
@ -232,7 +232,7 @@ Next we want to set up our `entry.component.ts` file so that it renders a login
import { Component } from '@angular/core'; import { Component } from '@angular/core';
import { UserService } from '@ng-mfe/shared/data-access-user'; import { UserService } from '@ng-mfe/shared/data-access-user';
@Component({ @Component({
selector: 'ng-mfe-login-entry', selector: 'ng-mf-login-entry',
template: ` template: `
<div class="login-app"> <div class="login-app">
<form class="login-form" (ngSubmit)="login()"> <form class="login-form" (ngSubmit)="login()">
@ -330,7 +330,7 @@ import { Router } from '@angular/router';
import { distinctUntilChanged } from 'rxjs/operators'; import { distinctUntilChanged } from 'rxjs/operators';
import { UserService } from '@ng-mfe/shared/data-access-user'; import { UserService } from '@ng-mfe/shared/data-access-user';
@Component({ @Component({
selector: 'ng-mfe-root', selector: 'ng-mf-root',
template: ` template: `
<div class="dashboard-nav">Admin Dashboard</div> <div class="dashboard-nav">Admin Dashboard</div>
<div *ngIf="isLoggedIn$ | async; else signIn"> <div *ngIf="isLoggedIn$ | async; else signIn">
@ -399,7 +399,7 @@ Well start by creating this file. Add a `module-federation.manifest.json` fil
Next, open `main.ts` under the `src/`folder and replace it with the following: Next, open `main.ts` under the `src/`folder and replace it with the following:
```typescript ```typescript
import { setRemoteDefinitions } from '@nrwl/angular/mfe'; import { setRemoteDefinitions } from '@nrwl/angular/mf';
fetch('/assets/module-federation.manifest.json') fetch('/assets/module-federation.manifest.json')
.then((res) => res.json()) .then((res) => res.json())
@ -453,7 +453,7 @@ Replace it with the following:
You will also need to add the following import to the top of the file: You will also need to add the following import to the top of the file:
```typescript ```typescript
import { loadRemoteModule } from '@nrwl/angular/mfe'; import { loadRemoteModule } from '@nrwl/angular/mf';
``` ```
The `loadRemoteModule` helper method simply hides some logic that will check if the Remote application has been loaded, and if not, load it, and then requests the correct exposed module from it. The `loadRemoteModule` helper method simply hides some logic that will check if the Remote application has been loaded, and if not, load it, and then requests the correct exposed module from it.

View File

@ -1,18 +1,18 @@
import { import {
checkFilesExist, checkFilesExist,
cleanupProject,
getSize, getSize,
killPorts, killPorts,
newProject, newProject,
cleanupProject, promisifiedTreeKill,
readFile,
runCLI, runCLI,
runCommandUntil,
runCypressTests,
tmpProjPath, tmpProjPath,
uniq, uniq,
updateFile, updateFile,
runCypressTests,
updateProjectConfig, updateProjectConfig,
readFile,
runCommandUntil,
promisifiedTreeKill,
} from '@nrwl/e2e/utils'; } from '@nrwl/e2e/utils';
import { ChildProcess } from 'child_process'; import { ChildProcess } from 'child_process';
@ -222,7 +222,7 @@ describe('Angular Projects', () => {
expect(buildOutput).toContain('Successfully ran target build'); expect(buildOutput).toContain('Successfully ran target build');
}); });
it('MFE - should serve the host and remote apps successfully, even with a shared library with a secondary entry point between them', async () => { it('MF - should serve the host and remote apps successfully, even with a shared library with a secondary entry point between them', async () => {
// ACT + ASSERT // ACT + ASSERT
const port1 = 4200; const port1 = 4200;
const port2 = 4206; const port2 = 4206;
@ -343,7 +343,7 @@ describe('Angular Projects', () => {
} }
}, 300000); }, 300000);
it('MFE - should build the host app successfully', async () => { it('MF - should build the host app successfully', async () => {
// ARRANGE // ARRANGE
const hostApp = uniq('app'); const hostApp = uniq('app');
const remoteApp1 = uniq('remote'); const remoteApp1 = uniq('remote');

View File

@ -77,8 +77,8 @@ describe('nx-dev: Packages Section', () => {
path: '/packages/angular/generators/scam-pipe', path: '/packages/angular/generators/scam-pipe',
}, },
{ {
title: '@nrwl/angular:setup-mfe', title: '@nrwl/angular:setup-mf',
path: '/packages/angular/generators/setup-mfe', path: '/packages/angular/generators/setup-mf',
}, },
{ {
title: '@nrwl/angular:setup-tailwind', title: '@nrwl/angular:setup-tailwind',

View File

@ -33,14 +33,20 @@ const schemaUrls = {
'/angular/library': '/packages/angular/generators/library', '/angular/library': '/packages/angular/generators/library',
'/angular/library-secondary-entry-point': '/angular/library-secondary-entry-point':
'/packages/angular/generators/library-secondary-entry-point', '/packages/angular/generators/library-secondary-entry-point',
'/angular/mfe-host': '/packages/angular/generators/mfe-host', '/angular/mfe-host': '/packages/angular/generators/mf-host',
'/angular/mfe-remote': '/packages/angular/generators/mfe-remote', '/angular/mfe-remote': '/packages/angular/generators/mf-remote',
'/packages/angular/generators/mfe-host':
'/packages/angular/generators/mf-host',
'/packages/angular/generators/mfe-remote':
'/packages/angular/generators/mf-remote',
'/angular/move': '/packages/angular/generators/move', '/angular/move': '/packages/angular/generators/move',
'/angular/ngrx': '/packages/angular/generators/ngrx', '/angular/ngrx': '/packages/angular/generators/ngrx',
'/angular/scam': '/packages/angular/generators/scam', '/angular/scam': '/packages/angular/generators/scam',
'/angular/scam-directive': '/packages/angular/generators/scam-directive', '/angular/scam-directive': '/packages/angular/generators/scam-directive',
'/angular/scam-pipe': '/packages/angular/generators/scam-pipe', '/angular/scam-pipe': '/packages/angular/generators/scam-pipe',
'/angular/setup-mfe': '/packages/angular/generators/setup-mfe', '/angular/setup-mfe': '/packages/angular/generators/setup-mf',
'/packages/angular/generators/setup-mfe':
'/packages/angular/generators/setup-mf',
'/angular/setup-tailwind': '/packages/angular/generators/setup-tailwind', '/angular/setup-tailwind': '/packages/angular/generators/setup-tailwind',
'/angular/stories': '/packages/angular/generators/stories', '/angular/stories': '/packages/angular/generators/stories',
'/angular/storybook-configuration': '/angular/storybook-configuration':

View File

@ -121,9 +121,9 @@
"schema": "./src/generators/scam-pipe/schema.json", "schema": "./src/generators/scam-pipe/schema.json",
"description": "Generate a pipe with an accompanying Single Component Angular Module (SCAM)." "description": "Generate a pipe with an accompanying Single Component Angular Module (SCAM)."
}, },
"setup-mfe": { "setup-mf": {
"factory": "./src/generators/setup-mfe/setup-mfe.compat", "factory": "./src/generators/setup-mf/setup-mf.compat",
"schema": "./src/generators/setup-mfe/schema.json", "schema": "./src/generators/setup-mf/schema.json",
"description": "Generate a Module Federation configuration for a given Angular application." "description": "Generate a Module Federation configuration for a given Angular application."
}, },
"setup-tailwind": { "setup-tailwind": {
@ -277,9 +277,9 @@
"schema": "./src/generators/scam-pipe/schema.json", "schema": "./src/generators/scam-pipe/schema.json",
"description": "Generate a pipe with an accompanying Single Component Angular Module (SCAM)." "description": "Generate a pipe with an accompanying Single Component Angular Module (SCAM)."
}, },
"setup-mfe": { "setup-mf": {
"factory": "./src/generators/setup-mfe/setup-mfe", "factory": "./src/generators/setup-mf/setup-mf",
"schema": "./src/generators/setup-mfe/schema.json", "schema": "./src/generators/setup-mf/schema.json",
"description": "Generate a Module Federation configuration for a given Angular application." "description": "Generate a Module Federation configuration for a given Angular application."
}, },
"setup-tailwind": { "setup-tailwind": {

View File

@ -12,7 +12,7 @@ export * from './src/generators/setup-tailwind/setup-tailwind';
export * from './src/generators/stories/stories'; export * from './src/generators/stories/stories';
export * from './src/generators/storybook-configuration/storybook-configuration'; export * from './src/generators/storybook-configuration/storybook-configuration';
export * from './src/generators/upgrade-module/upgrade-module'; export * from './src/generators/upgrade-module/upgrade-module';
export * from './src/generators/setup-mfe/setup-mfe'; export * from './src/generators/setup-mf/setup-mf';
export * from './src/generators/host/host'; export * from './src/generators/host/host';
export * from './src/generators/scam/scam'; export * from './src/generators/scam/scam';
export * from './src/generators/scam-directive/scam-directive'; export * from './src/generators/scam-directive/scam-directive';

View File

@ -2,4 +2,4 @@ export {
setRemoteUrlResolver, setRemoteUrlResolver,
setRemoteDefinitions, setRemoteDefinitions,
loadRemoteModule, loadRemoteModule,
} from './mfe'; } from './mf';

View File

@ -89,11 +89,11 @@
"description": "A lot of changes to how MFEs operate were discovered and merged without appropriate migrations. This should cover migrating existing MFEs to the latest, using ESM and optmized production bundles.", "description": "A lot of changes to how MFEs operate were discovered and merged without appropriate migrations. This should cover migrating existing MFEs to the latest, using ESM and optmized production bundles.",
"factory": "./src/migrations/update-13-5-0/update-mfe-configs" "factory": "./src/migrations/update-13-5-0/update-mfe-configs"
}, },
"add-cypress-mfe-workaround": { "add-cypress-mf-workaround": {
"cli": "nx", "cli": "nx",
"version": "13.8.1", "version": "13.8.1",
"description": "Angular doesn't attach styles.js to index.html with type=module in dev mode, meaning an error is written to the console. Cypress falls over on this error. Add logic to Cypress e2e projects to ignore this error.", "description": "Angular doesn't attach styles.js to index.html with type=module in dev mode, meaning an error is written to the console. Cypress falls over on this error. Add logic to Cypress e2e projects to ignore this error.",
"factory": "./src/migrations/update-13-8-1/add-cypress-mfe-workaround" "factory": "./src/migrations/update-13-8-1/add-cypress-mf-workaround"
}, },
"migrate-karma-config": { "migrate-karma-config": {
"cli": "nx", "cli": "nx",
@ -148,6 +148,12 @@
"version": "14.2.0-beta.6", "version": "14.2.0-beta.6",
"description": "Update `initialNavigation: 'enabled'` to `initialNavigation: 'enabledBlocking'`.", "description": "Update `initialNavigation: 'enabled'` to `initialNavigation: 'enabledBlocking'`.",
"factory": "./src/migrations/update-14-2-0/update-router-initial-navigation" "factory": "./src/migrations/update-14-2-0/update-router-initial-navigation"
},
"migrate-mfe-to-mf": {
"cli": "nx",
"version": "14.5.0-beta.0",
"description": "Update any references of MFE to MF.",
"factory": "./src/migrations/update-14-5-0/migrate-mfe-to-mf"
} }
}, },
"packageJsonUpdates": { "packageJsonUpdates": {

View File

@ -1,2 +1,2 @@
export { withModuleFederation } from '../src/utils/mfe/with-module-federation'; export { withModuleFederation } from '../src/utils/mf/with-module-federation';
export * from '../src/utils/mfe/mfe-webpack'; export * from '../src/utils/mf/mf-webpack';

View File

@ -1,24 +1,24 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`app --mfe should add a remote application and add it to a specified host applications webpack config that contains a remote application already 1`] = ` exports[`app --mf should add a remote application and add it to a specified host applications webpack config that contains a remote application already 1`] = `
"const { withModuleFederation } = require('@nrwl/angular/module-federation'); "const { withModuleFederation } = require('@nrwl/angular/module-federation');
const config = require('./module-federation.config'); const config = require('./module-federation.config');
module.exports = withModuleFederation(config);" module.exports = withModuleFederation(config);"
`; `;
exports[`app --mfe should add a remote application and add it to a specified host applications webpack config when no other remote has been added to it 1`] = ` exports[`app --mf should add a remote application and add it to a specified host applications webpack config when no other remote has been added to it 1`] = `
"const { withModuleFederation } = require('@nrwl/angular/module-federation'); "const { withModuleFederation } = require('@nrwl/angular/module-federation');
const config = require('./module-federation.config'); const config = require('./module-federation.config');
module.exports = withModuleFederation(config);" module.exports = withModuleFederation(config);"
`; `;
exports[`app --mfe should generate a Module Federation correctly for a each app 1`] = ` exports[`app --mf should generate a Module Federation correctly for a each app 1`] = `
"const { withModuleFederation } = require('@nrwl/angular/module-federation'); "const { withModuleFederation } = require('@nrwl/angular/module-federation');
const config = require('./module-federation.config'); const config = require('./module-federation.config');
module.exports = withModuleFederation(config);" module.exports = withModuleFederation(config);"
`; `;
exports[`app --mfe should generate a Module Federation correctly for a each app 2`] = ` exports[`app --mf should generate a Module Federation correctly for a each app 2`] = `
"const { withModuleFederation } = require('@nrwl/angular/module-federation'); "const { withModuleFederation } = require('@nrwl/angular/module-federation');
const config = require('./module-federation.config'); const config = require('./module-federation.config');
module.exports = withModuleFederation(config);" module.exports = withModuleFederation(config);"

View File

@ -906,11 +906,11 @@ describe('app', () => {
}); });
}); });
describe('--mfe', () => { describe('--mf', () => {
test.each(['host', 'remote'])( test.each(['host', 'remote'])(
'should generate a Module Federation correctly for a each app', 'should generate a Module Federation correctly for a each app',
async (type: 'host' | 'remote') => { async (type: 'host' | 'remote') => {
await generateApp(appTree, 'my-app', { mfe: true, mfeType: type }); await generateApp(appTree, 'my-app', { mf: true, mfType: type });
expect(appTree.exists(`apps/my-app/webpack.config.js`)).toBeTruthy(); expect(appTree.exists(`apps/my-app/webpack.config.js`)).toBeTruthy();
expect( expect(
@ -925,7 +925,7 @@ describe('app', () => {
test.each(['host', 'remote'])( test.each(['host', 'remote'])(
'should update the builder to use webpack-browser', 'should update the builder to use webpack-browser',
async (type: 'host' | 'remote') => { async (type: 'host' | 'remote') => {
await generateApp(appTree, 'my-app', { mfe: true, mfeType: type }); await generateApp(appTree, 'my-app', { mf: true, mfType: type });
const projectConfig = readProjectConfiguration(appTree, 'my-app'); const projectConfig = readProjectConfiguration(appTree, 'my-app');
@ -938,14 +938,14 @@ describe('app', () => {
it('should add a remote application and add it to a specified host applications webpack config when no other remote has been added to it', async () => { it('should add a remote application and add it to a specified host applications webpack config when no other remote has been added to it', async () => {
// ARRANGE // ARRANGE
await generateApp(appTree, 'app1', { await generateApp(appTree, 'app1', {
mfe: true, mf: true,
mfeType: 'host', mfType: 'host',
}); });
// ACT // ACT
await generateApp(appTree, 'remote1', { await generateApp(appTree, 'remote1', {
mfe: true, mf: true,
mfeType: 'remote', mfType: 'remote',
host: 'app1', host: 'app1',
}); });
@ -960,21 +960,21 @@ describe('app', () => {
it('should add a remote application and add it to a specified host applications webpack config that contains a remote application already', async () => { it('should add a remote application and add it to a specified host applications webpack config that contains a remote application already', async () => {
// ARRANGE // ARRANGE
await generateApp(appTree, 'app1', { await generateApp(appTree, 'app1', {
mfe: true, mf: true,
mfeType: 'host', mfType: 'host',
}); });
await generateApp(appTree, 'remote1', { await generateApp(appTree, 'remote1', {
mfe: true, mf: true,
mfeType: 'remote', mfType: 'remote',
host: 'app1', host: 'app1',
port: 4201, port: 4201,
}); });
// ACT // ACT
await generateApp(appTree, 'remote2', { await generateApp(appTree, 'remote2', {
mfe: true, mf: true,
mfeType: 'remote', mfType: 'remote',
host: 'app1', host: 'app1',
port: 4202, port: 4202,
}); });
@ -987,7 +987,7 @@ describe('app', () => {
expect(hostWebpackConfig).toMatchSnapshot(); expect(hostWebpackConfig).toMatchSnapshot();
}); });
it('should add a port to a non-mfe app', async () => { it('should add a port to a non-mf app', async () => {
// ACT // ACT
await generateApp(appTree, 'app1', { await generateApp(appTree, 'app1', {
port: 4205, port: 4205,

View File

@ -12,7 +12,7 @@ import { setupTailwindGenerator } from '../setup-tailwind/setup-tailwind';
import { import {
addE2e, addE2e,
addLinting, addLinting,
addMfe, addMf,
addProxyConfig, addProxyConfig,
addRouterRootConfiguration, addRouterRootConfiguration,
addUnitTestRunner, addUnitTestRunner,
@ -126,8 +126,8 @@ export async function applicationGenerator(
}); });
} }
if (options.mfe) { if (options.mf) {
await addMfe(host, options); await addMf(host, options);
} }
if (!options.skipFormat) { if (!options.skipFormat) {

View File

@ -1,12 +1,12 @@
import type { Tree } from '@nrwl/devkit'; import type { Tree } from '@nrwl/devkit';
import type { NormalizedSchema } from './normalized-schema'; import type { NormalizedSchema } from './normalized-schema';
import { setupMfe } from '../../setup-mfe/setup-mfe'; import { setupMf } from '../../setup-mf/setup-mf';
export async function addMfe(host: Tree, options: NormalizedSchema) { export async function addMf(host: Tree, options: NormalizedSchema) {
await setupMfe(host, { await setupMf(host, {
appName: options.name, appName: options.name,
mfeType: options.mfeType, mfType: options.mfType,
port: options.port, port: options.port,
remotes: options.remotes, remotes: options.remotes,
host: options.host, host: options.host,

View File

@ -1,6 +1,6 @@
export * from './add-e2e'; export * from './add-e2e';
export * from './add-linting'; export * from './add-linting';
export * from './add-mfe'; export * from './add-mf';
export * from './add-protractor'; export * from './add-protractor';
export * from './add-proxy-config'; export * from './add-proxy-config';
export * from './add-unit-test-runner'; export * from './add-unit-test-runner';

View File

@ -23,8 +23,8 @@ export interface Schema {
backendProject?: string; backendProject?: string;
strict?: boolean; strict?: boolean;
standaloneConfig?: boolean; standaloneConfig?: boolean;
mfe?: boolean; mf?: boolean;
mfeType?: 'host' | 'remote'; mfType?: 'host' | 'remote';
remotes?: string[]; remotes?: string[];
port?: number; port?: number;
host?: string; host?: string;

View File

@ -133,13 +133,13 @@
"description": "Split the project configuration into `<projectRoot>/project.json` rather than including it inside `workspace.json`.", "description": "Split the project configuration into `<projectRoot>/project.json` rather than including it inside `workspace.json`.",
"type": "boolean" "type": "boolean"
}, },
"mfe": { "mf": {
"description": "Generate a Module Federation configuration for the application", "description": "Generate a Module Federation configuration for the application",
"type": "boolean", "type": "boolean",
"default": false, "default": false,
"x-deprecated": "Use the `host` or `remote` generators instead. Support for generating Module Federation applications using the application generator will be removed in an upcoming version." "x-deprecated": "Use the `host` or `remote` generators instead. Support for generating Module Federation applications using the application generator will be removed in an upcoming version."
}, },
"mfeType": { "mfType": {
"type": "string", "type": "string",
"enum": ["host", "remote"], "enum": ["host", "remote"],
"description": "Type of application to generate the Module Federation configuration for.", "description": "Type of application to generate the Module Federation configuration for.",

View File

@ -23,8 +23,8 @@ describe('Host App Generator', () => {
await applicationGenerator(tree, { await applicationGenerator(tree, {
name: 'remote', name: 'remote',
mfe: true, mf: true,
mfeType: 'remote', mfType: 'remote',
routing: true, routing: true,
port: 4201, port: 4201,
}); });

View File

@ -31,8 +31,8 @@ export default async function host(tree: Tree, options: Schema) {
const installTask = await applicationGenerator(tree, { const installTask = await applicationGenerator(tree, {
...options, ...options,
mfe: true, mf: true,
mfeType: 'host', mfType: 'host',
routing: true, routing: true,
remotes: remotesToIntegrate ?? [], remotes: remotesToIntegrate ?? [],
port: 4200, port: 4200,

View File

@ -1,18 +1,18 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`MFE Remote App Generator should generate a remote mfe app with a host 1`] = ` exports[`MF Remote App Generator should generate a remote mf app with a host 1`] = `
"const { withModuleFederation } = require('@nrwl/angular/module-federation'); "const { withModuleFederation } = require('@nrwl/angular/module-federation');
const config = require('./module-federation.config'); const config = require('./module-federation.config');
module.exports = withModuleFederation(config);" module.exports = withModuleFederation(config);"
`; `;
exports[`MFE Remote App Generator should generate a remote mfe app with a host 2`] = ` exports[`MF Remote App Generator should generate a remote mf app with a host 2`] = `
"const { withModuleFederation } = require('@nrwl/angular/module-federation'); "const { withModuleFederation } = require('@nrwl/angular/module-federation');
const config = require('./module-federation.config'); const config = require('./module-federation.config');
module.exports = withModuleFederation(config);" module.exports = withModuleFederation(config);"
`; `;
exports[`MFE Remote App Generator should generate a remote mfe app with no host 1`] = ` exports[`MF Remote App Generator should generate a remote mf app with no host 1`] = `
"const { withModuleFederation } = require('@nrwl/angular/module-federation'); "const { withModuleFederation } = require('@nrwl/angular/module-federation');
const config = require('./module-federation.config'); const config = require('./module-federation.config');
module.exports = withModuleFederation(config);" module.exports = withModuleFederation(config);"

View File

@ -3,8 +3,8 @@ import remote from './remote';
import applicationGenerator from '../application/application'; import applicationGenerator from '../application/application';
import { readProjectConfiguration } from '@nrwl/devkit'; import { readProjectConfiguration } from '@nrwl/devkit';
describe('MFE Remote App Generator', () => { describe('MF Remote App Generator', () => {
it('should generate a remote mfe app with no host', async () => { it('should generate a remote mf app with no host', async () => {
// ARRANGE // ARRANGE
const tree = createTreeWithEmptyWorkspace(2); const tree = createTreeWithEmptyWorkspace(2);
@ -18,14 +18,14 @@ describe('MFE Remote App Generator', () => {
expect(tree.read('apps/test/webpack.config.js', 'utf-8')).toMatchSnapshot(); expect(tree.read('apps/test/webpack.config.js', 'utf-8')).toMatchSnapshot();
}); });
it('should generate a remote mfe app with a host', async () => { it('should generate a remote mf app with a host', async () => {
// ARRANGE // ARRANGE
const tree = createTreeWithEmptyWorkspace(2); const tree = createTreeWithEmptyWorkspace(2);
await applicationGenerator(tree, { await applicationGenerator(tree, {
name: 'host', name: 'host',
mfe: true, mf: true,
mfeType: 'host', mfType: 'host',
routing: true, routing: true,
}); });
@ -60,7 +60,7 @@ describe('MFE Remote App Generator', () => {
} }
}); });
it('should generate a remote mfe app and automatically find the next port available', async () => { it('should generate a remote mf app and automatically find the next port available', async () => {
// ARRANGE // ARRANGE
const tree = createTreeWithEmptyWorkspace(2); const tree = createTreeWithEmptyWorkspace(2);
await remote(tree, { await remote(tree, {
@ -78,7 +78,7 @@ describe('MFE Remote App Generator', () => {
expect(project.targets.serve.options.port).toEqual(4202); expect(project.targets.serve.options.port).toEqual(4202);
}); });
it('should generate a remote mfe app and automatically find the next port available even when there are no other targets', async () => { it('should generate a remote mf app and automatically find the next port available even when there are no other targets', async () => {
// ARRANGE // ARRANGE
const tree = createTreeWithEmptyWorkspace(2); const tree = createTreeWithEmptyWorkspace(2);

View File

@ -10,11 +10,11 @@ import { getMFProjects } from '../../utils/get-mf-projects';
import { normalizeProjectName } from '../utils/project'; import { normalizeProjectName } from '../utils/project';
function findNextAvailablePort(tree: Tree) { function findNextAvailablePort(tree: Tree) {
const mfeProjects = getMFProjects(tree); const mfProjects = getMFProjects(tree);
const ports = new Set<number>([4200]); const ports = new Set<number>([4200]);
for (const mfeProject of mfeProjects) { for (const mfProject of mfProjects) {
const { targets } = readProjectConfiguration(tree, mfeProject); const { targets } = readProjectConfiguration(tree, mfProject);
const port = targets?.serve?.options?.port ?? 4200; const port = targets?.serve?.options?.port ?? 4200;
ports.add(port); ports.add(port);
} }
@ -34,8 +34,8 @@ export default async function remote(tree: Tree, options: Schema) {
const installTask = await applicationGenerator(tree, { const installTask = await applicationGenerator(tree, {
...options, ...options,
mfe: true, mf: true,
mfeType: 'remote', mfType: 'remote',
routing: true, routing: true,
host: options.host, host: options.host,
port: options.port ?? findNextAvailablePort(tree), port: options.port ?? findNextAvailablePort(tree),

View File

@ -1,7 +1,7 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Init MFE --federationType=dynamic should create a host with the correct configurations 1`] = ` exports[`Init MF --federationType=dynamic should create a host with the correct configurations 1`] = `
"import { setRemoteDefinitions } from '@nrwl/angular/mfe'; "import { setRemoteDefinitions } from '@nrwl/angular/mf';
fetch('/assets/module-federation.manifest.json') fetch('/assets/module-federation.manifest.json')
.then((res) => res.json()) .then((res) => res.json())
@ -9,7 +9,7 @@ exports[`Init MFE --federationType=dynamic should create a host with the correct
.then(() => import('./bootstrap').catch(err => console.error(err)))" .then(() => import('./bootstrap').catch(err => console.error(err)))"
`; `;
exports[`Init MFE should add a remote application and add it to a specified host applications router config 1`] = ` exports[`Init MF should add a remote application and add it to a specified host applications router config 1`] = `
"import { NgModule } from '@angular/core'; "import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser'; import { BrowserModule } from '@angular/platform-browser';
@ -39,28 +39,28 @@ export class AppModule { }
" "
`; `;
exports[`Init MFE should add a remote application and add it to a specified host applications webpack config that contains a remote application already 1`] = ` exports[`Init MF should add a remote application and add it to a specified host applications webpack config that contains a remote application already 1`] = `
"module.exports = { "module.exports = {
name: 'app1', name: 'app1',
remotes: ['remote1','remote2',] remotes: ['remote1','remote2',]
}" }"
`; `;
exports[`Init MFE should add a remote application and add it to a specified host applications webpack config when no other remote has been added to it 1`] = ` exports[`Init MF should add a remote application and add it to a specified host applications webpack config when no other remote has been added to it 1`] = `
"module.exports = { "module.exports = {
name: 'app1', name: 'app1',
remotes: ['remote1',] remotes: ['remote1',]
}" }"
`; `;
exports[`Init MFE should add a remote to dynamic host correctly 1`] = ` exports[`Init MF should add a remote to dynamic host correctly 1`] = `
"import { NgModule } from '@angular/core'; "import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser'; import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component'; import { AppComponent } from './app.component';
import { NxWelcomeComponent } from './nx-welcome.component'; import { NxWelcomeComponent } from './nx-welcome.component';
import { RouterModule } from '@angular/router'; import { RouterModule } from '@angular/router';
import { loadRemoteModule } from '@nrwl/angular/mfe'; import { loadRemoteModule } from '@nrwl/angular/mf';
@NgModule({ @NgModule({
declarations: [ declarations: [
@ -81,26 +81,26 @@ export class AppModule { }
" "
`; `;
exports[`Init MFE should create webpack and mfe configs correctly 1`] = ` exports[`Init MF should create webpack and mf configs correctly 1`] = `
"const { withModuleFederation } = require('@nrwl/angular/module-federation'); "const { withModuleFederation } = require('@nrwl/angular/module-federation');
const config = require('./module-federation.config'); const config = require('./module-federation.config');
module.exports = withModuleFederation(config);" module.exports = withModuleFederation(config);"
`; `;
exports[`Init MFE should create webpack and mfe configs correctly 2`] = ` exports[`Init MF should create webpack and mf configs correctly 2`] = `
"module.exports = { "module.exports = {
name: 'app1', name: 'app1',
remotes: [] remotes: []
}" }"
`; `;
exports[`Init MFE should create webpack and mfe configs correctly 3`] = ` exports[`Init MF should create webpack and mf configs correctly 3`] = `
"const { withModuleFederation } = require('@nrwl/angular/module-federation'); "const { withModuleFederation } = require('@nrwl/angular/module-federation');
const config = require('./module-federation.config'); const config = require('./module-federation.config');
module.exports = withModuleFederation(config);" module.exports = withModuleFederation(config);"
`; `;
exports[`Init MFE should create webpack and mfe configs correctly 4`] = ` exports[`Init MF should create webpack and mf configs correctly 4`] = `
"module.exports = { "module.exports = {
name: 'remote1', name: 'remote1',
exposes: { exposes: {
@ -109,7 +109,7 @@ exports[`Init MFE should create webpack and mfe configs correctly 4`] = `
}" }"
`; `;
exports[`Init MFE should generate the remote entry component correctly when prefix is not provided 1`] = ` exports[`Init MF should generate the remote entry component correctly when prefix is not provided 1`] = `
"import { Component } from '@angular/core'; "import { Component } from '@angular/core';
@Component({ @Component({
@ -120,7 +120,7 @@ export class RemoteEntryComponent {}
" "
`; `;
exports[`Init MFE should generate the remote entry module and component correctly 1`] = ` exports[`Init MF should generate the remote entry module and component correctly 1`] = `
"import { Component } from '@angular/core'; "import { Component } from '@angular/core';
@Component({ @Component({
@ -131,7 +131,7 @@ export class RemoteEntryComponent {}
" "
`; `;
exports[`Init MFE should generate the remote entry module and component correctly 2`] = ` exports[`Init MF should generate the remote entry module and component correctly 2`] = `
"import { NgModule } from '@angular/core'; "import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common'; import { CommonModule } from '@angular/common';

View File

@ -4,10 +4,10 @@ import type { Schema } from '../schema';
export function addEntryModule( export function addEntryModule(
host: Tree, host: Tree,
{ appName, routing, mfeType, prefix }: Schema, { appName, routing, mfType, prefix }: Schema,
appRoot: string appRoot: string
) { ) {
if (mfeType === 'remote') { if (mfType === 'remote') {
generateFiles( generateFiles(
host, host,
joinPathFragments(__dirname, '../files/entry-module-files'), joinPathFragments(__dirname, '../files/entry-module-files'),

View File

@ -13,8 +13,8 @@ import { ArrayLiteralExpression } from 'typescript';
import { addRoute } from '../../../utils/nx-devkit/ast-utils'; import { addRoute } from '../../../utils/nx-devkit/ast-utils';
import { insertImport } from '@nrwl/workspace/src/utilities/ast-utils'; import { insertImport } from '@nrwl/workspace/src/utilities/ast-utils';
export function checkIsCommaNeeded(mfeRemoteText: string) { export function checkIsCommaNeeded(mfRemoteText: string) {
const remoteText = mfeRemoteText.replace(/\s+/g, ''); const remoteText = mfRemoteText.replace(/\s+/g, '');
return !remoteText.endsWith(',]') return !remoteText.endsWith(',]')
? remoteText === '[]' ? remoteText === '[]'
? false ? false
@ -23,7 +23,7 @@ export function checkIsCommaNeeded(mfeRemoteText: string) {
} }
export function addRemoteToHost(tree: Tree, options: Schema) { export function addRemoteToHost(tree: Tree, options: Schema) {
if (options.mfeType === 'remote' && options.host) { if (options.mfType === 'remote' && options.host) {
const hostProject = readProjectConfiguration(tree, options.host); const hostProject = readProjectConfiguration(tree, options.host);
const pathToMFManifest = joinPathFragments( const pathToMFManifest = joinPathFragments(
hostProject.sourceRoot, hostProject.sourceRoot,
@ -57,9 +57,9 @@ export function addRemoteToHost(tree: Tree, options: Schema) {
function determineHostFederationType( function determineHostFederationType(
tree: Tree, tree: Tree,
pathToMfeManifest: string pathToMfManifest: string
): 'dynamic' | 'static' { ): 'dynamic' | 'static' {
return tree.exists(pathToMfeManifest) ? 'dynamic' : 'static'; return tree.exists(pathToMfManifest) ? 'dynamic' : 'static';
} }
function addRemoteToStaticHost( function addRemoteToStaticHost(
@ -99,9 +99,9 @@ function addRemoteToStaticHost(
function addRemoteToDynamicHost( function addRemoteToDynamicHost(
tree: Tree, tree: Tree,
options: Schema, options: Schema,
pathToMfeManifest: string pathToMfManifest: string
) { ) {
updateJson(tree, pathToMfeManifest, (manifest) => { updateJson(tree, pathToMfManifest, (manifest) => {
return { return {
...manifest, ...manifest,
[options.appName]: `http://localhost:${options.port}`, [options.appName]: `http://localhost:${options.port}`,
@ -139,7 +139,7 @@ function addLazyLoadedRouteToHostAppModule(
sourceFile, sourceFile,
pathToHostAppModule, pathToHostAppModule,
'loadRemoteModule', 'loadRemoteModule',
'@nrwl/angular/mfe' '@nrwl/angular/mf'
); );
} }
const routeToAdd = const routeToAdd =

View File

@ -1,7 +1,6 @@
import type { Tree } from '@nrwl/devkit'; import type { Tree } from '@nrwl/devkit';
import type { Schema } from '../schema';
import { joinPathFragments } from '@nrwl/devkit'; import { joinPathFragments } from '@nrwl/devkit';
import type { Schema } from '../schema';
export function fixBootstrap(tree: Tree, appRoot: string, options: Schema) { export function fixBootstrap(tree: Tree, appRoot: string, options: Schema) {
const mainFilePath = joinPathFragments(appRoot, 'src/main.ts'); const mainFilePath = joinPathFragments(appRoot, 'src/main.ts');
@ -10,7 +9,7 @@ export function fixBootstrap(tree: Tree, appRoot: string, options: Schema) {
const bootstrapImportCode = `import('./bootstrap').catch(err => console.error(err))`; const bootstrapImportCode = `import('./bootstrap').catch(err => console.error(err))`;
const fetchMFManifestCode = `import { setRemoteDefinitions } from '@nrwl/angular/mfe'; const fetchMFManifestCode = `import { setRemoteDefinitions } from '@nrwl/angular/mf';
fetch('/assets/module-federation.manifest.json') fetch('/assets/module-federation.manifest.json')
.then((res) => res.json()) .then((res) => res.json())
@ -19,7 +18,7 @@ export function fixBootstrap(tree: Tree, appRoot: string, options: Schema) {
tree.write( tree.write(
mainFilePath, mainFilePath,
options.mfeType === 'host' && options.federationType === 'dynamic' options.mfType === 'host' && options.federationType === 'dynamic'
? fetchMFManifestCode ? fetchMFManifestCode
: bootstrapImportCode : bootstrapImportCode
); );

View File

@ -25,7 +25,7 @@ export function generateWebpackConfig(
appRoot, appRoot,
{ {
tmpl: '', tmpl: '',
type: options.mfeType, type: options.mfType,
name: options.appName, name: options.appName,
remotes: remotesWithPorts ?? [], remotes: remotesWithPorts ?? [],
projectRoot: appRoot, projectRoot: appRoot,

View File

@ -1,13 +1,12 @@
import type { Tree } from '@nrwl/devkit'; import type { Tree } from '@nrwl/devkit';
import type { Schema } from '../schema';
import { readProjectConfiguration } from '@nrwl/devkit'; import { readProjectConfiguration } from '@nrwl/devkit';
import type { Schema } from '../schema';
export function getRemotesWithPorts(host: Tree, options: Schema) { export function getRemotesWithPorts(host: Tree, options: Schema) {
// If type is host and remotes supplied, check remotes exist // If type is host and remotes supplied, check remotes exist
const remotesWithPort: { remoteName: string; port: number }[] = []; const remotesWithPort: { remoteName: string; port: number }[] = [];
if ( if (
options.mfeType === 'host' && options.mfType === 'host' &&
Array.isArray(options.remotes) && Array.isArray(options.remotes) &&
options.remotes.length > 0 options.remotes.length > 0
) { ) {

View File

@ -1,10 +1,9 @@
import type { Tree } from '@nrwl/devkit'; import type { Tree } from '@nrwl/devkit';
import { joinPathFragments, readProjectConfiguration } from '@nrwl/devkit';
import type { Schema } from '../schema'; import type { Schema } from '../schema';
import { readProjectConfiguration, joinPathFragments } from '@nrwl/devkit';
export function setupHostIfDynamic(tree: Tree, options: Schema) { export function setupHostIfDynamic(tree: Tree, options: Schema) {
if (options.federationType === 'static' || options.mfeType === 'remote') { if (options.federationType === 'static' || options.mfType === 'remote') {
return; return;
} }

View File

@ -1,10 +1,9 @@
import type { Tree } from '@nrwl/devkit'; import type { Tree } from '@nrwl/devkit';
import type { Schema } from '../schema';
import { import {
readProjectConfiguration, readProjectConfiguration,
updateProjectConfiguration, updateProjectConfiguration,
} from '@nrwl/devkit'; } from '@nrwl/devkit';
import type { Schema } from '../schema';
export function setupServeTarget(host: Tree, options: Schema) { export function setupServeTarget(host: Tree, options: Schema) {
const appConfig = readProjectConfiguration(host, options.appName); const appConfig = readProjectConfiguration(host, options.appName);
@ -12,7 +11,7 @@ export function setupServeTarget(host: Tree, options: Schema) {
appConfig.targets['serve'] = { appConfig.targets['serve'] = {
...appConfig.targets['serve'], ...appConfig.targets['serve'],
executor: executor:
options.mfeType === 'host' options.mfType === 'host'
? '@nrwl/angular:module-federation-dev-server' ? '@nrwl/angular:module-federation-dev-server'
: '@nrwl/angular:webpack-server', : '@nrwl/angular:webpack-server',
options: { options: {
@ -22,7 +21,7 @@ export function setupServeTarget(host: Tree, options: Schema) {
}, },
}; };
if (options.mfeType === 'remote') { if (options.mfType === 'remote') {
appConfig.targets['serve-static'] = { appConfig.targets['serve-static'] = {
executor: '@nrwl/angular:file-server', executor: '@nrwl/angular:file-server',
defaultConfiguration: 'development', defaultConfiguration: 'development',

View File

@ -1,6 +1,6 @@
export interface Schema { export interface Schema {
appName: string; appName: string;
mfeType: 'host' | 'remote'; mfType: 'host' | 'remote';
port?: number; port?: number;
remotes?: string[]; remotes?: string[];
host?: string; host?: string;

View File

@ -1,6 +1,6 @@
{ {
"$schema": "http://json-schema.org/schema", "$schema": "http://json-schema.org/schema",
"$id": "GeneratorAngularMFESetup", "$id": "GeneratorAngularMFSetup",
"cli": "nx", "cli": "nx",
"title": "Generate Module Federation Setup for Angular App", "title": "Generate Module Federation Setup for Angular App",
"description": "Create Module Federation configuration files for given Angular Application.", "description": "Create Module Federation configuration files for given Angular Application.",
@ -15,7 +15,7 @@
}, },
"x-prompt": "What app would you like to generate a Module Federation configuration for?" "x-prompt": "What app would you like to generate a Module Federation configuration for?"
}, },
"mfeType": { "mfType": {
"type": "string", "type": "string",
"enum": ["host", "remote"], "enum": ["host", "remote"],
"description": "Type of application to generate the Module Federation configuration for.", "description": "Type of application to generate the Module Federation configuration for.",
@ -61,6 +61,6 @@
"description": "The prefix to use for any generated component." "description": "The prefix to use for any generated component."
} }
}, },
"required": ["appName", "mfeType"], "required": ["appName", "mfType"],
"additionalProperties": false "additionalProperties": false
} }

View File

@ -0,0 +1,4 @@
import { convertNxGenerator } from '@nrwl/devkit';
import { setupMf } from './setup-mf';
export default convertNxGenerator(setupMf);

View File

@ -1,10 +1,10 @@
import { readJson, Tree } from '@nrwl/devkit'; import { readJson, readProjectConfiguration, Tree } from '@nrwl/devkit';
import { readProjectConfiguration } from '@nrwl/devkit';
import { createTreeWithEmptyWorkspace } from '@nrwl/devkit/testing'; import { createTreeWithEmptyWorkspace } from '@nrwl/devkit/testing';
import { setupMfe } from './setup-mfe'; import { setupMf } from './setup-mf';
import applicationGenerator from '../application/application'; import applicationGenerator from '../application/application';
describe('Init MFE', () => {
describe('Init MF', () => {
let tree: Tree; let tree: Tree;
beforeEach(async () => { beforeEach(async () => {
@ -23,12 +23,12 @@ describe('Init MFE', () => {
['app1', 'host'], ['app1', 'host'],
['remote1', 'remote'], ['remote1', 'remote'],
])( ])(
'should create webpack and mfe configs correctly', 'should create webpack and mf configs correctly',
async (app, type: 'host' | 'remote') => { async (app, type: 'host' | 'remote') => {
// ACT // ACT
await setupMfe(tree, { await setupMf(tree, {
appName: app, appName: app,
mfeType: type, mfType: type,
}); });
// ASSERT // ASSERT
@ -44,11 +44,11 @@ describe('Init MFE', () => {
); );
expect(webpackContents).toMatchSnapshot(); expect(webpackContents).toMatchSnapshot();
const mfeConfigContents = tree.read( const mfConfigContents = tree.read(
`apps/${app}/module-federation.config.js`, `apps/${app}/module-federation.config.js`,
'utf-8' 'utf-8'
); );
expect(mfeConfigContents).toMatchSnapshot(); expect(mfConfigContents).toMatchSnapshot();
} }
); );
@ -62,9 +62,9 @@ describe('Init MFE', () => {
const mainContents = tree.read(`apps/${app}/src/main.ts`, 'utf-8'); const mainContents = tree.read(`apps/${app}/src/main.ts`, 'utf-8');
// ACT // ACT
await setupMfe(tree, { await setupMf(tree, {
appName: app, appName: app,
mfeType: type, mfType: type,
}); });
// ASSERT // ASSERT
@ -89,9 +89,9 @@ describe('Init MFE', () => {
const mainContents = tree.read(`apps/${app}/src/main.ts`, 'utf-8'); const mainContents = tree.read(`apps/${app}/src/main.ts`, 'utf-8');
// ACT // ACT
await setupMfe(tree, { await setupMf(tree, {
appName: app, appName: app,
mfeType: type, mfType: type,
}); });
// ASSERT // ASSERT
@ -111,9 +111,9 @@ describe('Init MFE', () => {
'should change the build and serve target and set correct path to webpack config', 'should change the build and serve target and set correct path to webpack config',
async (app, type: 'host' | 'remote') => { async (app, type: 'host' | 'remote') => {
// ACT // ACT
await setupMfe(tree, { await setupMf(tree, {
appName: app, appName: app,
mfeType: type, mfType: type,
}); });
// ASSERT // ASSERT
@ -133,9 +133,9 @@ describe('Init MFE', () => {
it('should generate the remote entry module and component correctly', async () => { it('should generate the remote entry module and component correctly', async () => {
// ACT // ACT
await setupMfe(tree, { await setupMf(tree, {
appName: 'remote1', appName: 'remote1',
mfeType: 'remote', mfType: 'remote',
prefix: 'my-org', prefix: 'my-org',
}); });
@ -150,7 +150,7 @@ describe('Init MFE', () => {
it('should generate the remote entry component correctly when prefix is not provided', async () => { it('should generate the remote entry component correctly when prefix is not provided', async () => {
// ACT // ACT
await setupMfe(tree, { appName: 'remote1', mfeType: 'remote' }); await setupMf(tree, { appName: 'remote1', mfType: 'remote' });
// ASSERT // ASSERT
expect( expect(
@ -160,41 +160,41 @@ describe('Init MFE', () => {
it('should add the remote config to the host when --remotes flag supplied', async () => { it('should add the remote config to the host when --remotes flag supplied', async () => {
// ACT // ACT
await setupMfe(tree, { await setupMf(tree, {
appName: 'app1', appName: 'app1',
mfeType: 'host', mfType: 'host',
remotes: ['remote1'], remotes: ['remote1'],
}); });
// ASSERT // ASSERT
const mfeConfigContents = tree.read( const mfConfigContents = tree.read(
`apps/app1/module-federation.config.js`, `apps/app1/module-federation.config.js`,
'utf-8' 'utf-8'
); );
expect(mfeConfigContents).toContain(`'remote1'`); expect(mfConfigContents).toContain(`'remote1'`);
}); });
it('should add a remote application and add it to a specified host applications webpack config when no other remote has been added to it', async () => { it('should add a remote application and add it to a specified host applications webpack config when no other remote has been added to it', async () => {
// ARRANGE // ARRANGE
await setupMfe(tree, { await setupMf(tree, {
appName: 'app1', appName: 'app1',
mfeType: 'host', mfType: 'host',
}); });
// ACT // ACT
await setupMfe(tree, { await setupMf(tree, {
appName: 'remote1', appName: 'remote1',
mfeType: 'remote', mfType: 'remote',
host: 'app1', host: 'app1',
}); });
// ASSERT // ASSERT
const hostMfeConfig = tree.read( const hostMfConfig = tree.read(
'apps/app1/module-federation.config.js', 'apps/app1/module-federation.config.js',
'utf-8' 'utf-8'
); );
expect(hostMfeConfig).toMatchSnapshot(); expect(hostMfConfig).toMatchSnapshot();
}); });
it('should add a remote application and add it to a specified host applications webpack config that contains a remote application already', async () => { it('should add a remote application and add it to a specified host applications webpack config that contains a remote application already', async () => {
@ -203,32 +203,32 @@ describe('Init MFE', () => {
name: 'remote2', name: 'remote2',
}); });
await setupMfe(tree, { await setupMf(tree, {
appName: 'app1', appName: 'app1',
mfeType: 'host', mfType: 'host',
}); });
await setupMfe(tree, { await setupMf(tree, {
appName: 'remote1', appName: 'remote1',
mfeType: 'remote', mfType: 'remote',
host: 'app1', host: 'app1',
port: 4201, port: 4201,
}); });
// ACT // ACT
await setupMfe(tree, { await setupMf(tree, {
appName: 'remote2', appName: 'remote2',
mfeType: 'remote', mfType: 'remote',
host: 'app1', host: 'app1',
port: 4202, port: 4202,
}); });
// ASSERT // ASSERT
const hostMfeConfig = tree.read( const hostMfConfig = tree.read(
'apps/app1/module-federation.config.js', 'apps/app1/module-federation.config.js',
'utf-8' 'utf-8'
); );
expect(hostMfeConfig).toMatchSnapshot(); expect(hostMfConfig).toMatchSnapshot();
}); });
it('should add a remote application and add it to a specified host applications router config', async () => { it('should add a remote application and add it to a specified host applications router config', async () => {
@ -238,24 +238,24 @@ describe('Init MFE', () => {
routing: true, routing: true,
}); });
await setupMfe(tree, { await setupMf(tree, {
appName: 'app1', appName: 'app1',
mfeType: 'host', mfType: 'host',
routing: true, routing: true,
}); });
await setupMfe(tree, { await setupMf(tree, {
appName: 'remote1', appName: 'remote1',
mfeType: 'remote', mfType: 'remote',
host: 'app1', host: 'app1',
port: 4201, port: 4201,
routing: true, routing: true,
}); });
// ACT // ACT
await setupMfe(tree, { await setupMf(tree, {
appName: 'remote2', appName: 'remote2',
mfeType: 'remote', mfType: 'remote',
host: 'app1', host: 'app1',
port: 4202, port: 4202,
routing: true, routing: true,
@ -274,9 +274,9 @@ describe('Init MFE', () => {
}); });
// ACT // ACT
await setupMfe(tree, { await setupMf(tree, {
appName: 'test-app', appName: 'test-app',
mfeType: 'host', mfType: 'host',
routing: true, routing: true,
}); });
@ -293,9 +293,9 @@ describe('Init MFE', () => {
describe('--federationType=dynamic', () => { describe('--federationType=dynamic', () => {
it('should create a host with the correct configurations', async () => { it('should create a host with the correct configurations', async () => {
// ARRANGE & ACT // ARRANGE & ACT
await setupMfe(tree, { await setupMf(tree, {
appName: 'app1', appName: 'app1',
mfeType: 'host', mfType: 'host',
routing: true, routing: true,
federationType: 'dynamic', federationType: 'dynamic',
}); });
@ -313,17 +313,17 @@ describe('Init MFE', () => {
it('should add a remote to dynamic host correctly', async () => { it('should add a remote to dynamic host correctly', async () => {
// ARRANGE // ARRANGE
await setupMfe(tree, { await setupMf(tree, {
appName: 'app1', appName: 'app1',
mfeType: 'host', mfType: 'host',
routing: true, routing: true,
federationType: 'dynamic', federationType: 'dynamic',
}); });
// ACT // ACT
await setupMfe(tree, { await setupMf(tree, {
appName: 'remote1', appName: 'remote1',
mfeType: 'remote', mfType: 'remote',
port: 4201, port: 4201,
host: 'app1', host: 'app1',
routing: true, routing: true,

View File

@ -1,8 +1,7 @@
import type { Tree } from '@nrwl/devkit'; import type { Tree } from '@nrwl/devkit';
import { formatFiles, readProjectConfiguration } from '@nrwl/devkit';
import type { Schema } from './schema'; import type { Schema } from './schema';
import { readProjectConfiguration, formatFiles } from '@nrwl/devkit';
import { import {
addCypressOnErrorWorkaround, addCypressOnErrorWorkaround,
addEntryModule, addEntryModule,
@ -11,12 +10,12 @@ import {
fixBootstrap, fixBootstrap,
generateWebpackConfig, generateWebpackConfig,
getRemotesWithPorts, getRemotesWithPorts,
setupServeTarget,
setupHostIfDynamic, setupHostIfDynamic,
setupServeTarget,
updateTsConfigTarget, updateTsConfigTarget,
} from './lib'; } from './lib';
export async function setupMfe(tree: Tree, options: Schema) { export async function setupMf(tree: Tree, options: Schema) {
const projectConfig = readProjectConfiguration(tree, options.appName); const projectConfig = readProjectConfiguration(tree, options.appName);
options.federationType = options.federationType ?? 'static'; options.federationType = options.federationType ?? 'static';
@ -43,4 +42,4 @@ export async function setupMfe(tree: Tree, options: Schema) {
} }
} }
export default setupMfe; export default setupMf;

View File

@ -1,4 +0,0 @@
import { convertNxGenerator } from '@nrwl/devkit';
import { setupMfe } from './setup-mfe';
export default convertNxGenerator(setupMfe);

View File

@ -1,8 +1,8 @@
import { removeProjectConfiguration, Tree } from '@nrwl/devkit'; import { removeProjectConfiguration } from '@nrwl/devkit';
import { createTreeWithEmptyWorkspace } from '@nrwl/devkit/testing'; import { createTreeWithEmptyWorkspace } from '@nrwl/devkit/testing';
import applicationGenerator from '../../generators/application/application'; import applicationGenerator from '../../generators/application/application';
import setupMfe from '../../generators/setup-mfe/setup-mfe'; import setupMf from '../../generators/setup-mf/setup-mf';
import addCypressMfeWorkaround from './add-cypress-mfe-workaround'; import addCypressMfWorkaround from './add-cypress-mf-workaround';
describe('Add Cypress MFE Workaround', () => { describe('Add Cypress MFE Workaround', () => {
it('should add the cypress command to the index.ts for project that has associated e2e', async () => { it('should add the cypress command to the index.ts for project that has associated e2e', async () => {
@ -13,12 +13,12 @@ describe('Add Cypress MFE Workaround', () => {
routing: true, routing: true,
}); });
await setupMfe(tree, { appName: 'app1', mfeType: 'host', routing: true }); await setupMf(tree, { appName: 'app1', mfType: 'host', routing: true });
tree.write('apps/app1-e2e/src/support/index.ts', ''); tree.write('apps/app1-e2e/src/support/index.ts', '');
// ACT // ACT
await addCypressMfeWorkaround(tree); await addCypressMfWorkaround(tree);
// ASSERT // ASSERT
expect(tree.read('apps/app1-e2e/src/support/index.ts', 'utf-8')).toContain( expect(tree.read('apps/app1-e2e/src/support/index.ts', 'utf-8')).toContain(
@ -34,13 +34,13 @@ describe('Add Cypress MFE Workaround', () => {
routing: true, routing: true,
}); });
await setupMfe(tree, { appName: 'app1', mfeType: 'host', routing: true }); await setupMf(tree, { appName: 'app1', mfType: 'host', routing: true });
removeProjectConfiguration(tree, 'app1-e2e'); removeProjectConfiguration(tree, 'app1-e2e');
tree.delete('apps/app1-e2e'); tree.delete('apps/app1-e2e');
// ACT // ACT
await addCypressMfeWorkaround(tree); await addCypressMfWorkaround(tree);
// ASSERT // ASSERT
expect(tree.exists('apps/app1-e2e/src/support/index.ts')).toBeFalsy(); expect(tree.exists('apps/app1-e2e/src/support/index.ts')).toBeFalsy();

View File

@ -0,0 +1,229 @@
import type { Tree } from '@nrwl/devkit';
import { createTreeWithEmptyWorkspace } from '@nrwl/devkit/testing';
import migrateMfeToMf, {
renameSetupMfeGeneratorUsages,
replaceExportedMFETypes,
replaceNrwlAngularMfImport,
} from './migrate-mfe-to-mf';
describe('migrate-mfe-to-mf', () => {
let tree: Tree;
beforeEach(() => {
tree = createTreeWithEmptyWorkspace(2);
});
it('should replace any imports from nrwl/angular/mfe', () => {
// ARRANGE
const file = `import { loadRemoteModule } from '@nrwl/angular/mfe';
// But not comments, or other markdown etc @nrwl/angular/mfe
function something() {
// but this should change
import('@nrwl/angular/mfe');
}
`;
// ACT
const updatedFile = replaceNrwlAngularMfImport(file);
// ASSERT
expect(updatedFile).toMatchInlineSnapshot(`
"import { loadRemoteModule } from '@nrwl/angular/mf';
// But not comments, or other markdown etc @nrwl/angular/mfe
function something() {
// but this should change
import('@nrwl/angular/mf');
}
"
`);
});
it('should replace type imports from nrwl/angular/module-federation', () => {
// ARRANGE
const file = `import { MFERemotes } from '@nrwl/angular/module-federation';
import { MFEConfig } from '@nrwl/angular/module-federation';
const myValue: MFEConfig = {};
const myRemotes: MFERemotes = [];
function doSomething(v: MFERemotes): MFEConfig {};
`;
// ACT
const updatedFile = replaceExportedMFETypes(file);
// ASSERT
expect(updatedFile).toMatchInlineSnapshot(`
"import { MFRemotes } from '@nrwl/angular/module-federation';
import { MFConfig } from '@nrwl/angular/module-federation';
const myValue: MFConfig = {};
const myRemotes: MFRemotes = [];
function doSomething(v: MFRemotes): MFConfig {};
"
`);
});
it('should rename usages of setupMfe', () => {
// ARRANGE
const file = `import { setupMfe } from '@nrwl/angular/generators';
import { setupMfe, somethingElse } from '@nrwl/angular/generators';
function doSomething(v: MFERemotes): MFEConfig {
setupMfe();
setupMfe({
mfeType: 'doSomething'
})
};
`;
// ACT
const updatedFile = renameSetupMfeGeneratorUsages(file);
// ASSERT
expect(updatedFile).toMatchInlineSnapshot(`
"import { setupMf } from '@nrwl/angular/generators';
import { setupMf, somethingElse } from '@nrwl/angular/generators';
function doSomething(v: MFERemotes): MFEConfig {
setupMf();
setupMf({
mfType: 'doSomething'
})
};
"
`);
});
it('should update files correctly', async () => {
// ARRANGE
tree.write(
'test1.js',
`import { loadRemoteModule } from '@nrwl/angular/mfe';
// But not comments, or other markdown etc @nrwl/angular/mfe
function something() {
// but this should change
import('@nrwl/angular/mfe');
}`
);
tree.write(
'test2.ts',
`import { MFERemotes } from '@nrwl/angular/module-federation';
import { MFEConfig } from '@nrwl/angular/module-federation';
const myValue: MFEConfig = {};
const myRemotes: MFERemotes = [];
function doSomething(v: MFERemotes): MFEConfig {};
`
);
tree.write(
'apps/app1/test3.ts',
`import { loadRemoteModule } from '@nrwl/angular/mfe';
import { MFERemotes, MFEConfig } from '@nrwl/angular/module-federation';
// But not comments, or other markdown etc @nrwl/angular/mfe
function something() {
// but this should change
import('@nrwl/angular/mfe');
}
const myValue: MFEConfig = {};
const myRemotes: MFERemotes = [];
function doSomething(v: MFERemotes): MFEConfig {};
`
);
tree.write(
'libs/plugins/my-plugin/src/generators/my-generator.ts',
`import { setupMfe } from '@nrwl/angular/generators';
import { setupMfe, somethingElse } from '@nrwl/angular/generators';
function doSomething(v: MFERemotes): MFEConfig {
setupMfe();
setupMfe({
mfeType: 'doSomething'
})
};
`
);
// ACT
await migrateMfeToMf(tree);
// ASSERT
expect(tree.read('test1.js', 'utf-8')).toMatchInlineSnapshot(`
"import { loadRemoteModule } from '@nrwl/angular/mf';
// But not comments, or other markdown etc @nrwl/angular/mfe
function something() {
// but this should change
import('@nrwl/angular/mf');
}"
`);
expect(tree.read('test2.ts', 'utf-8')).toMatchInlineSnapshot(`
"import { MFRemotes } from '@nrwl/angular/module-federation';
import { MFConfig } from '@nrwl/angular/module-federation';
const myValue: MFConfig = {};
const myRemotes: MFRemotes = [];
function doSomething(v: MFRemotes): MFConfig {};
"
`);
expect(tree.read('apps/app1/test3.ts', 'utf-8')).toMatchInlineSnapshot(`
"import { loadRemoteModule } from '@nrwl/angular/mf';
import { MFRemotes, MFConfig } from '@nrwl/angular/module-federation';
// But not comments, or other markdown etc @nrwl/angular/mfe
function something() {
// but this should change
import('@nrwl/angular/mf');
}
const myValue: MFConfig = {};
const myRemotes: MFRemotes = [];
function doSomething(v: MFRemotes): MFConfig {};
"
`);
expect(
tree.read(
'libs/plugins/my-plugin/src/generators/my-generator.ts',
'utf-8'
)
).toMatchInlineSnapshot(`
"import { setupMf } from '@nrwl/angular/generators';
import { setupMf, somethingElse } from '@nrwl/angular/generators';
function doSomething(v: MFERemotes): MFEConfig {
setupMf();
setupMf({
mfType: 'doSomething'
})
};
"
`);
});
});

View File

@ -0,0 +1,144 @@
import type { Tree } from '@nrwl/devkit';
import { visitNotIgnoredFiles } from '@nrwl/devkit';
import { extname } from 'path';
import { tsquery } from '@phenomnomnominal/tsquery';
import { SourceFile } from 'typescript';
const NRWL_ANGULAR_MFE_STATIC_IMPORT_SELECTOR =
'ImportDeclaration > StringLiteral[value="@nrwl/angular/mfe"]';
const NRWL_ANGULAR_MFE_DYNAMIC_IMPORT_SELECTOR =
'CallExpression:has(ImportKeyword) > StringLiteral[value="@nrwl/angular/mfe"]';
const NRWL_ANGULAR_MFE_TYPES_SELECTOR =
'ImportDeclaration:has(StringLiteral[value=@nrwl/angular/module-federation]) > ImportClause > NamedImports';
export function replaceNrwlAngularMfImport(fileContents: string) {
let fileAst: SourceFile = tsquery.ast(fileContents);
if (fileContents.includes('@nrwl/angular/mfe')) {
// This file definitely contains the string, however, we're interested in whether it is an import
const staticQueryResult = tsquery(
fileAst,
NRWL_ANGULAR_MFE_STATIC_IMPORT_SELECTOR,
{
visitAllChildren: true,
}
);
if (staticQueryResult && staticQueryResult.length > 0) {
fileContents = `${fileContents.slice(
0,
staticQueryResult[0].getStart()
)}'@nrwl/angular/mf'${fileContents.slice(staticQueryResult[0].getEnd())}`;
}
fileAst = tsquery.ast(fileContents);
const dynamicQueryResult = tsquery(
fileAst,
NRWL_ANGULAR_MFE_DYNAMIC_IMPORT_SELECTOR,
{
visitAllChildren: true,
}
);
if (dynamicQueryResult && dynamicQueryResult.length > 0) {
fileContents = `${fileContents.slice(
0,
dynamicQueryResult[0].getStart()
)}'@nrwl/angular/mf'${fileContents.slice(
dynamicQueryResult[0].getEnd()
)}`;
}
}
return fileContents;
}
export function replaceExportedMFETypes(fileContents: string) {
const ast = tsquery.ast(fileContents);
const queryResult = tsquery(ast, NRWL_ANGULAR_MFE_TYPES_SELECTOR, {
visitAllChildren: true,
});
if (queryResult && queryResult.length > 0) {
const TYPES_IMPORTED_FROM_NRWL_REGEX =
/(MFERemotes|MFEConfig)+.*from+.+(@nrwl\/angular\/module-federation)+/g;
if (TYPES_IMPORTED_FROM_NRWL_REGEX.test(fileContents)) {
fileContents = fileContents.replace(/MFERemotes/g, 'MFRemotes');
fileContents = fileContents.replace(/MFEConfig/g, 'MFConfig');
}
}
return fileContents;
}
export function renameSetupMfeGeneratorUsages(fileContents: string) {
// Attempt to update any custom generator usage of the changed generators
const NRWL_SETUP_MFE_IMPORT_SELECTOR =
'ImportDeclaration:has(StringLiteral[value=@nrwl/angular/generators]) > ImportClause:has(NamedImports:has(ImportSpecifier > Identifier[name=setupMfe]))';
const SETUP_MFE_IMPORTED_FROM_NRWL_REGEX =
/(setupMfe)+.*from+.+(@nrwl\/angular\/generators)+/g;
const SETUP_MFE_FUNCTION_CALL_MFE_TYPE_PROPERTY_ASSIGNMENT_SELECTOR =
'CallExpression:has(Identifier[name=setupMf]) ObjectLiteralExpression > PropertyAssignment > Identifier[name=mfeType]';
let ast = tsquery.ast(fileContents);
let queryResult = tsquery(ast, NRWL_SETUP_MFE_IMPORT_SELECTOR, {
visitAllChildren: true,
});
if (
queryResult &&
queryResult.length > 0 &&
SETUP_MFE_IMPORTED_FROM_NRWL_REGEX.test(fileContents)
) {
fileContents = fileContents.replace(/setupMfe/g, 'setupMf');
}
ast = tsquery.ast(fileContents);
queryResult = tsquery(
ast,
SETUP_MFE_FUNCTION_CALL_MFE_TYPE_PROPERTY_ASSIGNMENT_SELECTOR,
{
visitAllChildren: true,
}
);
while (queryResult && queryResult.length > 0) {
const node = queryResult[0];
fileContents = `${fileContents.slice(
0,
node.getStart()
)}mfType${fileContents.slice(node.getEnd())}`;
ast = tsquery.ast(fileContents);
queryResult = tsquery(
ast,
SETUP_MFE_FUNCTION_CALL_MFE_TYPE_PROPERTY_ASSIGNMENT_SELECTOR,
{
visitAllChildren: true,
}
);
}
return fileContents;
}
export default async function (tree: Tree) {
visitNotIgnoredFiles(tree, '/', (path) => {
const pathExtName = extname(path);
let fileContents = tree.read(path, 'utf-8');
if (pathExtName === '.ts' || pathExtName === '.js') {
fileContents = replaceNrwlAngularMfImport(fileContents);
}
if (pathExtName === '.ts') {
// Only TS files can import types and interfaces
fileContents = replaceExportedMFETypes(fileContents);
fileContents = renameSetupMfeGeneratorUsages(fileContents);
}
tree.write(path, fileContents);
});
}

View File

@ -4,9 +4,9 @@ import * as fs from 'fs';
import * as tsUtils from '@nrwl/workspace/src/utilities/typescript'; import * as tsUtils from '@nrwl/workspace/src/utilities/typescript';
import * as devkit from '@nrwl/devkit'; import * as devkit from '@nrwl/devkit';
import { sharePackages, shareWorkspaceLibraries } from './mfe-webpack'; import { sharePackages, shareWorkspaceLibraries } from './mf-webpack';
describe('MFE Webpack Utils', () => { describe('MF Webpack Utils', () => {
afterEach(() => jest.clearAllMocks()); afterEach(() => jest.clearAllMocks());
describe('ShareWorkspaceLibraries', () => { describe('ShareWorkspaceLibraries', () => {
@ -20,7 +20,7 @@ describe('MFE Webpack Utils', () => {
} catch (error) { } catch (error) {
// ASSERT // ASSERT
expect(error.message).toContain( expect(error.message).toContain(
'NX MFE: TsConfig Path for workspace libraries does not exist!' 'NX MF: TsConfig Path for workspace libraries does not exist!'
); );
} }
}); });
@ -79,7 +79,7 @@ describe('MFE Webpack Utils', () => {
} catch (error) { } catch (error) {
// ASSERT // ASSERT
expect(error.message).toEqual( expect(error.message).toEqual(
'NX MFE: Could not find root package.json to determine dependency versions.' 'NX MF: Could not find root package.json to determine dependency versions.'
); );
} }
}); });

View File

@ -87,7 +87,7 @@ export function shareWorkspaceLibraries(
) { ) {
if (!existsSync(tsConfigPath)) { if (!existsSync(tsConfigPath)) {
throw new Error( throw new Error(
`NX MFE: TsConfig Path for workspace libraries does not exist! (${tsConfigPath})` `NX MF: TsConfig Path for workspace libraries does not exist! (${tsConfigPath})`
); );
} }

View File

@ -8,7 +8,7 @@ export function readRootPackageJson(): {
const pkgJsonPath = joinPathFragments(workspaceRoot, 'package.json'); const pkgJsonPath = joinPathFragments(workspaceRoot, 'package.json');
if (!existsSync(pkgJsonPath)) { if (!existsSync(pkgJsonPath)) {
throw new Error( throw new Error(
'NX MFE: Could not find root package.json to determine dependency versions.' 'NX MF: Could not find root package.json to determine dependency versions.'
); );
} }

View File

@ -3,7 +3,7 @@ import {
SharedLibraryConfig, SharedLibraryConfig,
sharePackages, sharePackages,
shareWorkspaceLibraries, shareWorkspaceLibraries,
} from './mfe-webpack'; } from './mf-webpack';
import { import {
createProjectGraphAsync, createProjectGraphAsync,
ProjectGraph, ProjectGraph,
@ -16,10 +16,10 @@ import {
import { ParsedCommandLine } from 'typescript'; import { ParsedCommandLine } from 'typescript';
import { readRootPackageJson } from './utils'; import { readRootPackageJson } from './utils';
import { extname, join } from 'path'; import { extname, join } from 'path';
import ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin');
import { readCachedProjectConfiguration } from 'nx/src/project-graph/project-graph'; import { readCachedProjectConfiguration } from 'nx/src/project-graph/project-graph';
import ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin');
export type MFERemotes = string[] | [remoteName: string, remoteUrl: string][]; export type MFRemotes = string[] | [remoteName: string, remoteUrl: string][];
type SharedFunction = ( type SharedFunction = (
libraryName: string, libraryName: string,
@ -31,9 +31,9 @@ type AdditionalSharedConfig = Array<
| { libraryName: string; sharedConfig: SharedLibraryConfig } | { libraryName: string; sharedConfig: SharedLibraryConfig }
>; >;
export interface MFEConfig { export interface MFConfig {
name: string; name: string;
remotes?: MFERemotes; remotes?: MFRemotes;
exposes?: Record<string, string>; exposes?: Record<string, string>;
shared?: SharedFunction; shared?: SharedFunction;
additionalShared?: AdditionalSharedConfig; additionalShared?: AdditionalSharedConfig;
@ -134,7 +134,7 @@ function determineRemoteUrl(remote: string) {
}/remoteEntry.mjs`; }/remoteEntry.mjs`;
} }
function mapRemotes(remotes: MFERemotes) { function mapRemotes(remotes: MFRemotes) {
const mappedRemotes = {}; const mappedRemotes = {};
for (const remote of remotes) { for (const remote of remotes) {
@ -233,8 +233,8 @@ function applyDefaultEagerPackages(
} }
} }
export async function withModuleFederation(options: MFEConfig) { export async function withModuleFederation(options: MFConfig) {
const DEFAULT_NPM_PACKAGES_TO_AVOID = ['zone.js', '@nrwl/angular/mfe']; const DEFAULT_NPM_PACKAGES_TO_AVOID = ['zone.js', '@nrwl/angular/mf'];
let projectGraph: ProjectGraph<any>; let projectGraph: ProjectGraph<any>;
try { try {