feat(angular): replace mfe references with mf (#10957)
This commit is contained in:
parent
778f13fdaf
commit
37072bc5d6
@ -196,13 +196,13 @@
|
||||
"description": "Split the project configuration into `<projectRoot>/project.json` rather than including it inside `workspace.json`.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"mfe": {
|
||||
"mf": {
|
||||
"description": "Generate a Module Federation configuration for the application",
|
||||
"type": "boolean",
|
||||
"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."
|
||||
},
|
||||
"mfeType": {
|
||||
"mfType": {
|
||||
"type": "string",
|
||||
"enum": ["host", "remote"],
|
||||
"description": "Type of application to generate the Module Federation configuration for.",
|
||||
@ -1732,11 +1732,11 @@
|
||||
"path": "/packages/angular/src/generators/scam-pipe/schema.json"
|
||||
},
|
||||
{
|
||||
"name": "setup-mfe",
|
||||
"factory": "./src/generators/setup-mfe/setup-mfe",
|
||||
"name": "setup-mf",
|
||||
"factory": "./src/generators/setup-mf/setup-mf",
|
||||
"schema": {
|
||||
"$schema": "http://json-schema.org/schema",
|
||||
"$id": "GeneratorAngularMFESetup",
|
||||
"$id": "GeneratorAngularMFSetup",
|
||||
"cli": "nx",
|
||||
"title": "Generate Module Federation Setup for Angular App",
|
||||
"description": "Create Module Federation configuration files for given Angular Application.",
|
||||
@ -1748,7 +1748,7 @@
|
||||
"$default": { "$source": "argv", "index": 0 },
|
||||
"x-prompt": "What app would you like to generate a Module Federation configuration for?"
|
||||
},
|
||||
"mfeType": {
|
||||
"mfType": {
|
||||
"type": "string",
|
||||
"enum": ["host", "remote"],
|
||||
"description": "Type of application to generate the Module Federation configuration for.",
|
||||
@ -1794,15 +1794,15 @@
|
||||
"description": "The prefix to use for any generated component."
|
||||
}
|
||||
},
|
||||
"required": ["appName", "mfeType"],
|
||||
"required": ["appName", "mfType"],
|
||||
"additionalProperties": false,
|
||||
"presets": []
|
||||
},
|
||||
"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": [],
|
||||
"hidden": false,
|
||||
"path": "/packages/angular/src/generators/setup-mfe/schema.json"
|
||||
"path": "/packages/angular/src/generators/setup-mf/schema.json"
|
||||
},
|
||||
{
|
||||
"name": "setup-tailwind",
|
||||
|
||||
@ -39,7 +39,7 @@
|
||||
"scam",
|
||||
"scam-directive",
|
||||
"scam-pipe",
|
||||
"setup-mfe",
|
||||
"setup-mf",
|
||||
"setup-tailwind",
|
||||
"stories",
|
||||
"storybook-configuration",
|
||||
|
||||
@ -34,12 +34,12 @@ To start with, we need to create a new Nx Workspace. We can do this easily with:
|
||||
|
||||
```bash
|
||||
# Npm
|
||||
npx create-nx-workspace ng-mfe
|
||||
npx create-nx-workspace ng-mf
|
||||
```
|
||||
|
||||
```bash
|
||||
# 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.
|
||||
@ -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 { UserService } from '@ng-mfe/shared/data-access-user';
|
||||
@Component({
|
||||
selector: 'ng-mfe-login-entry',
|
||||
selector: 'ng-mf-login-entry',
|
||||
template: `
|
||||
<div class="login-app">
|
||||
<form class="login-form" (ngSubmit)="login()">
|
||||
@ -330,7 +330,7 @@ import { Router } from '@angular/router';
|
||||
import { distinctUntilChanged } from 'rxjs/operators';
|
||||
import { UserService } from '@ng-mfe/shared/data-access-user';
|
||||
@Component({
|
||||
selector: 'ng-mfe-root',
|
||||
selector: 'ng-mf-root',
|
||||
template: `
|
||||
<div class="dashboard-nav">Admin Dashboard</div>
|
||||
<div *ngIf="isLoggedIn$ | async; else signIn">
|
||||
@ -399,7 +399,7 @@ We’ll 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:
|
||||
|
||||
```typescript
|
||||
import { setRemoteDefinitions } from '@nrwl/angular/mfe';
|
||||
import { setRemoteDefinitions } from '@nrwl/angular/mf';
|
||||
|
||||
fetch('/assets/module-federation.manifest.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:
|
||||
|
||||
```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.
|
||||
|
||||
@ -1,18 +1,18 @@
|
||||
import {
|
||||
checkFilesExist,
|
||||
cleanupProject,
|
||||
getSize,
|
||||
killPorts,
|
||||
newProject,
|
||||
cleanupProject,
|
||||
promisifiedTreeKill,
|
||||
readFile,
|
||||
runCLI,
|
||||
runCommandUntil,
|
||||
runCypressTests,
|
||||
tmpProjPath,
|
||||
uniq,
|
||||
updateFile,
|
||||
runCypressTests,
|
||||
updateProjectConfig,
|
||||
readFile,
|
||||
runCommandUntil,
|
||||
promisifiedTreeKill,
|
||||
} from '@nrwl/e2e/utils';
|
||||
import { ChildProcess } from 'child_process';
|
||||
|
||||
@ -222,7 +222,7 @@ describe('Angular Projects', () => {
|
||||
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
|
||||
const port1 = 4200;
|
||||
const port2 = 4206;
|
||||
@ -343,7 +343,7 @@ describe('Angular Projects', () => {
|
||||
}
|
||||
}, 300000);
|
||||
|
||||
it('MFE - should build the host app successfully', async () => {
|
||||
it('MF - should build the host app successfully', async () => {
|
||||
// ARRANGE
|
||||
const hostApp = uniq('app');
|
||||
const remoteApp1 = uniq('remote');
|
||||
|
||||
@ -77,8 +77,8 @@ describe('nx-dev: Packages Section', () => {
|
||||
path: '/packages/angular/generators/scam-pipe',
|
||||
},
|
||||
{
|
||||
title: '@nrwl/angular:setup-mfe',
|
||||
path: '/packages/angular/generators/setup-mfe',
|
||||
title: '@nrwl/angular:setup-mf',
|
||||
path: '/packages/angular/generators/setup-mf',
|
||||
},
|
||||
{
|
||||
title: '@nrwl/angular:setup-tailwind',
|
||||
|
||||
@ -33,14 +33,20 @@ const schemaUrls = {
|
||||
'/angular/library': '/packages/angular/generators/library',
|
||||
'/angular/library-secondary-entry-point':
|
||||
'/packages/angular/generators/library-secondary-entry-point',
|
||||
'/angular/mfe-host': '/packages/angular/generators/mfe-host',
|
||||
'/angular/mfe-remote': '/packages/angular/generators/mfe-remote',
|
||||
'/angular/mfe-host': '/packages/angular/generators/mf-host',
|
||||
'/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/ngrx': '/packages/angular/generators/ngrx',
|
||||
'/angular/scam': '/packages/angular/generators/scam',
|
||||
'/angular/scam-directive': '/packages/angular/generators/scam-directive',
|
||||
'/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/stories': '/packages/angular/generators/stories',
|
||||
'/angular/storybook-configuration':
|
||||
|
||||
@ -121,9 +121,9 @@
|
||||
"schema": "./src/generators/scam-pipe/schema.json",
|
||||
"description": "Generate a pipe with an accompanying Single Component Angular Module (SCAM)."
|
||||
},
|
||||
"setup-mfe": {
|
||||
"factory": "./src/generators/setup-mfe/setup-mfe.compat",
|
||||
"schema": "./src/generators/setup-mfe/schema.json",
|
||||
"setup-mf": {
|
||||
"factory": "./src/generators/setup-mf/setup-mf.compat",
|
||||
"schema": "./src/generators/setup-mf/schema.json",
|
||||
"description": "Generate a Module Federation configuration for a given Angular application."
|
||||
},
|
||||
"setup-tailwind": {
|
||||
@ -277,9 +277,9 @@
|
||||
"schema": "./src/generators/scam-pipe/schema.json",
|
||||
"description": "Generate a pipe with an accompanying Single Component Angular Module (SCAM)."
|
||||
},
|
||||
"setup-mfe": {
|
||||
"factory": "./src/generators/setup-mfe/setup-mfe",
|
||||
"schema": "./src/generators/setup-mfe/schema.json",
|
||||
"setup-mf": {
|
||||
"factory": "./src/generators/setup-mf/setup-mf",
|
||||
"schema": "./src/generators/setup-mf/schema.json",
|
||||
"description": "Generate a Module Federation configuration for a given Angular application."
|
||||
},
|
||||
"setup-tailwind": {
|
||||
|
||||
@ -12,7 +12,7 @@ export * from './src/generators/setup-tailwind/setup-tailwind';
|
||||
export * from './src/generators/stories/stories';
|
||||
export * from './src/generators/storybook-configuration/storybook-configuration';
|
||||
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/scam/scam';
|
||||
export * from './src/generators/scam-directive/scam-directive';
|
||||
|
||||
@ -2,4 +2,4 @@ export {
|
||||
setRemoteUrlResolver,
|
||||
setRemoteDefinitions,
|
||||
loadRemoteModule,
|
||||
} from './mfe';
|
||||
} from './mf';
|
||||
@ -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.",
|
||||
"factory": "./src/migrations/update-13-5-0/update-mfe-configs"
|
||||
},
|
||||
"add-cypress-mfe-workaround": {
|
||||
"add-cypress-mf-workaround": {
|
||||
"cli": "nx",
|
||||
"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.",
|
||||
"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": {
|
||||
"cli": "nx",
|
||||
@ -148,6 +148,12 @@
|
||||
"version": "14.2.0-beta.6",
|
||||
"description": "Update `initialNavigation: 'enabled'` to `initialNavigation: 'enabledBlocking'`.",
|
||||
"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": {
|
||||
|
||||
@ -1,2 +1,2 @@
|
||||
export { withModuleFederation } from '../src/utils/mfe/with-module-federation';
|
||||
export * from '../src/utils/mfe/mfe-webpack';
|
||||
export { withModuleFederation } from '../src/utils/mf/with-module-federation';
|
||||
export * from '../src/utils/mf/mf-webpack';
|
||||
|
||||
@ -1,24 +1,24 @@
|
||||
// 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 config = require('./module-federation.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 config = require('./module-federation.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 config = require('./module-federation.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 config = require('./module-federation.config');
|
||||
module.exports = withModuleFederation(config);"
|
||||
|
||||
@ -906,11 +906,11 @@ describe('app', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('--mfe', () => {
|
||||
describe('--mf', () => {
|
||||
test.each(['host', 'remote'])(
|
||||
'should generate a Module Federation correctly for a each app',
|
||||
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(
|
||||
@ -925,7 +925,7 @@ describe('app', () => {
|
||||
test.each(['host', 'remote'])(
|
||||
'should update the builder to use webpack-browser',
|
||||
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');
|
||||
|
||||
@ -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 () => {
|
||||
// ARRANGE
|
||||
await generateApp(appTree, 'app1', {
|
||||
mfe: true,
|
||||
mfeType: 'host',
|
||||
mf: true,
|
||||
mfType: 'host',
|
||||
});
|
||||
|
||||
// ACT
|
||||
await generateApp(appTree, 'remote1', {
|
||||
mfe: true,
|
||||
mfeType: 'remote',
|
||||
mf: true,
|
||||
mfType: 'remote',
|
||||
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 () => {
|
||||
// ARRANGE
|
||||
await generateApp(appTree, 'app1', {
|
||||
mfe: true,
|
||||
mfeType: 'host',
|
||||
mf: true,
|
||||
mfType: 'host',
|
||||
});
|
||||
|
||||
await generateApp(appTree, 'remote1', {
|
||||
mfe: true,
|
||||
mfeType: 'remote',
|
||||
mf: true,
|
||||
mfType: 'remote',
|
||||
host: 'app1',
|
||||
port: 4201,
|
||||
});
|
||||
|
||||
// ACT
|
||||
await generateApp(appTree, 'remote2', {
|
||||
mfe: true,
|
||||
mfeType: 'remote',
|
||||
mf: true,
|
||||
mfType: 'remote',
|
||||
host: 'app1',
|
||||
port: 4202,
|
||||
});
|
||||
@ -987,7 +987,7 @@ describe('app', () => {
|
||||
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
|
||||
await generateApp(appTree, 'app1', {
|
||||
port: 4205,
|
||||
|
||||
@ -12,7 +12,7 @@ import { setupTailwindGenerator } from '../setup-tailwind/setup-tailwind';
|
||||
import {
|
||||
addE2e,
|
||||
addLinting,
|
||||
addMfe,
|
||||
addMf,
|
||||
addProxyConfig,
|
||||
addRouterRootConfiguration,
|
||||
addUnitTestRunner,
|
||||
@ -126,8 +126,8 @@ export async function applicationGenerator(
|
||||
});
|
||||
}
|
||||
|
||||
if (options.mfe) {
|
||||
await addMfe(host, options);
|
||||
if (options.mf) {
|
||||
await addMf(host, options);
|
||||
}
|
||||
|
||||
if (!options.skipFormat) {
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
import type { Tree } from '@nrwl/devkit';
|
||||
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) {
|
||||
await setupMfe(host, {
|
||||
export async function addMf(host: Tree, options: NormalizedSchema) {
|
||||
await setupMf(host, {
|
||||
appName: options.name,
|
||||
mfeType: options.mfeType,
|
||||
mfType: options.mfType,
|
||||
port: options.port,
|
||||
remotes: options.remotes,
|
||||
host: options.host,
|
||||
@ -1,6 +1,6 @@
|
||||
export * from './add-e2e';
|
||||
export * from './add-linting';
|
||||
export * from './add-mfe';
|
||||
export * from './add-mf';
|
||||
export * from './add-protractor';
|
||||
export * from './add-proxy-config';
|
||||
export * from './add-unit-test-runner';
|
||||
|
||||
@ -23,8 +23,8 @@ export interface Schema {
|
||||
backendProject?: string;
|
||||
strict?: boolean;
|
||||
standaloneConfig?: boolean;
|
||||
mfe?: boolean;
|
||||
mfeType?: 'host' | 'remote';
|
||||
mf?: boolean;
|
||||
mfType?: 'host' | 'remote';
|
||||
remotes?: string[];
|
||||
port?: number;
|
||||
host?: string;
|
||||
|
||||
@ -133,13 +133,13 @@
|
||||
"description": "Split the project configuration into `<projectRoot>/project.json` rather than including it inside `workspace.json`.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"mfe": {
|
||||
"mf": {
|
||||
"description": "Generate a Module Federation configuration for the application",
|
||||
"type": "boolean",
|
||||
"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."
|
||||
},
|
||||
"mfeType": {
|
||||
"mfType": {
|
||||
"type": "string",
|
||||
"enum": ["host", "remote"],
|
||||
"description": "Type of application to generate the Module Federation configuration for.",
|
||||
|
||||
@ -23,8 +23,8 @@ describe('Host App Generator', () => {
|
||||
|
||||
await applicationGenerator(tree, {
|
||||
name: 'remote',
|
||||
mfe: true,
|
||||
mfeType: 'remote',
|
||||
mf: true,
|
||||
mfType: 'remote',
|
||||
routing: true,
|
||||
port: 4201,
|
||||
});
|
||||
|
||||
@ -31,8 +31,8 @@ export default async function host(tree: Tree, options: Schema) {
|
||||
|
||||
const installTask = await applicationGenerator(tree, {
|
||||
...options,
|
||||
mfe: true,
|
||||
mfeType: 'host',
|
||||
mf: true,
|
||||
mfType: 'host',
|
||||
routing: true,
|
||||
remotes: remotesToIntegrate ?? [],
|
||||
port: 4200,
|
||||
|
||||
@ -1,18 +1,18 @@
|
||||
// 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 config = require('./module-federation.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 config = require('./module-federation.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 config = require('./module-federation.config');
|
||||
module.exports = withModuleFederation(config);"
|
||||
|
||||
@ -3,8 +3,8 @@ import remote from './remote';
|
||||
import applicationGenerator from '../application/application';
|
||||
import { readProjectConfiguration } from '@nrwl/devkit';
|
||||
|
||||
describe('MFE Remote App Generator', () => {
|
||||
it('should generate a remote mfe app with no host', async () => {
|
||||
describe('MF Remote App Generator', () => {
|
||||
it('should generate a remote mf app with no host', async () => {
|
||||
// ARRANGE
|
||||
const tree = createTreeWithEmptyWorkspace(2);
|
||||
|
||||
@ -18,14 +18,14 @@ describe('MFE Remote App Generator', () => {
|
||||
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
|
||||
const tree = createTreeWithEmptyWorkspace(2);
|
||||
|
||||
await applicationGenerator(tree, {
|
||||
name: 'host',
|
||||
mfe: true,
|
||||
mfeType: 'host',
|
||||
mf: true,
|
||||
mfType: 'host',
|
||||
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
|
||||
const tree = createTreeWithEmptyWorkspace(2);
|
||||
await remote(tree, {
|
||||
@ -78,7 +78,7 @@ describe('MFE Remote App Generator', () => {
|
||||
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
|
||||
const tree = createTreeWithEmptyWorkspace(2);
|
||||
|
||||
|
||||
@ -10,11 +10,11 @@ import { getMFProjects } from '../../utils/get-mf-projects';
|
||||
import { normalizeProjectName } from '../utils/project';
|
||||
|
||||
function findNextAvailablePort(tree: Tree) {
|
||||
const mfeProjects = getMFProjects(tree);
|
||||
const mfProjects = getMFProjects(tree);
|
||||
|
||||
const ports = new Set<number>([4200]);
|
||||
for (const mfeProject of mfeProjects) {
|
||||
const { targets } = readProjectConfiguration(tree, mfeProject);
|
||||
for (const mfProject of mfProjects) {
|
||||
const { targets } = readProjectConfiguration(tree, mfProject);
|
||||
const port = targets?.serve?.options?.port ?? 4200;
|
||||
ports.add(port);
|
||||
}
|
||||
@ -34,8 +34,8 @@ export default async function remote(tree: Tree, options: Schema) {
|
||||
|
||||
const installTask = await applicationGenerator(tree, {
|
||||
...options,
|
||||
mfe: true,
|
||||
mfeType: 'remote',
|
||||
mf: true,
|
||||
mfType: 'remote',
|
||||
routing: true,
|
||||
host: options.host,
|
||||
port: options.port ?? findNextAvailablePort(tree),
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Init MFE --federationType=dynamic should create a host with the correct configurations 1`] = `
|
||||
"import { setRemoteDefinitions } from '@nrwl/angular/mfe';
|
||||
exports[`Init MF --federationType=dynamic should create a host with the correct configurations 1`] = `
|
||||
"import { setRemoteDefinitions } from '@nrwl/angular/mf';
|
||||
|
||||
fetch('/assets/module-federation.manifest.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)))"
|
||||
`;
|
||||
|
||||
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 { 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 = {
|
||||
name: 'app1',
|
||||
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 = {
|
||||
name: 'app1',
|
||||
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 { BrowserModule } from '@angular/platform-browser';
|
||||
|
||||
import { AppComponent } from './app.component';
|
||||
import { NxWelcomeComponent } from './nx-welcome.component';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { loadRemoteModule } from '@nrwl/angular/mfe';
|
||||
import { loadRemoteModule } from '@nrwl/angular/mf';
|
||||
|
||||
@NgModule({
|
||||
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 config = require('./module-federation.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 = {
|
||||
name: 'app1',
|
||||
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 config = require('./module-federation.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 = {
|
||||
name: 'remote1',
|
||||
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';
|
||||
|
||||
@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';
|
||||
|
||||
@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 { CommonModule } from '@angular/common';
|
||||
|
||||
@ -4,10 +4,10 @@ import type { Schema } from '../schema';
|
||||
|
||||
export function addEntryModule(
|
||||
host: Tree,
|
||||
{ appName, routing, mfeType, prefix }: Schema,
|
||||
{ appName, routing, mfType, prefix }: Schema,
|
||||
appRoot: string
|
||||
) {
|
||||
if (mfeType === 'remote') {
|
||||
if (mfType === 'remote') {
|
||||
generateFiles(
|
||||
host,
|
||||
joinPathFragments(__dirname, '../files/entry-module-files'),
|
||||
@ -13,8 +13,8 @@ import { ArrayLiteralExpression } from 'typescript';
|
||||
import { addRoute } from '../../../utils/nx-devkit/ast-utils';
|
||||
import { insertImport } from '@nrwl/workspace/src/utilities/ast-utils';
|
||||
|
||||
export function checkIsCommaNeeded(mfeRemoteText: string) {
|
||||
const remoteText = mfeRemoteText.replace(/\s+/g, '');
|
||||
export function checkIsCommaNeeded(mfRemoteText: string) {
|
||||
const remoteText = mfRemoteText.replace(/\s+/g, '');
|
||||
return !remoteText.endsWith(',]')
|
||||
? remoteText === '[]'
|
||||
? false
|
||||
@ -23,7 +23,7 @@ export function checkIsCommaNeeded(mfeRemoteText: string) {
|
||||
}
|
||||
|
||||
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 pathToMFManifest = joinPathFragments(
|
||||
hostProject.sourceRoot,
|
||||
@ -57,9 +57,9 @@ export function addRemoteToHost(tree: Tree, options: Schema) {
|
||||
|
||||
function determineHostFederationType(
|
||||
tree: Tree,
|
||||
pathToMfeManifest: string
|
||||
pathToMfManifest: string
|
||||
): 'dynamic' | 'static' {
|
||||
return tree.exists(pathToMfeManifest) ? 'dynamic' : 'static';
|
||||
return tree.exists(pathToMfManifest) ? 'dynamic' : 'static';
|
||||
}
|
||||
|
||||
function addRemoteToStaticHost(
|
||||
@ -99,9 +99,9 @@ function addRemoteToStaticHost(
|
||||
function addRemoteToDynamicHost(
|
||||
tree: Tree,
|
||||
options: Schema,
|
||||
pathToMfeManifest: string
|
||||
pathToMfManifest: string
|
||||
) {
|
||||
updateJson(tree, pathToMfeManifest, (manifest) => {
|
||||
updateJson(tree, pathToMfManifest, (manifest) => {
|
||||
return {
|
||||
...manifest,
|
||||
[options.appName]: `http://localhost:${options.port}`,
|
||||
@ -139,7 +139,7 @@ function addLazyLoadedRouteToHostAppModule(
|
||||
sourceFile,
|
||||
pathToHostAppModule,
|
||||
'loadRemoteModule',
|
||||
'@nrwl/angular/mfe'
|
||||
'@nrwl/angular/mf'
|
||||
);
|
||||
}
|
||||
const routeToAdd =
|
||||
@ -1,7 +1,6 @@
|
||||
import type { Tree } from '@nrwl/devkit';
|
||||
import type { Schema } from '../schema';
|
||||
|
||||
import { joinPathFragments } from '@nrwl/devkit';
|
||||
import type { Schema } from '../schema';
|
||||
|
||||
export function fixBootstrap(tree: Tree, appRoot: string, options: Schema) {
|
||||
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 fetchMFManifestCode = `import { setRemoteDefinitions } from '@nrwl/angular/mfe';
|
||||
const fetchMFManifestCode = `import { setRemoteDefinitions } from '@nrwl/angular/mf';
|
||||
|
||||
fetch('/assets/module-federation.manifest.json')
|
||||
.then((res) => res.json())
|
||||
@ -19,7 +18,7 @@ export function fixBootstrap(tree: Tree, appRoot: string, options: Schema) {
|
||||
|
||||
tree.write(
|
||||
mainFilePath,
|
||||
options.mfeType === 'host' && options.federationType === 'dynamic'
|
||||
options.mfType === 'host' && options.federationType === 'dynamic'
|
||||
? fetchMFManifestCode
|
||||
: bootstrapImportCode
|
||||
);
|
||||
@ -25,7 +25,7 @@ export function generateWebpackConfig(
|
||||
appRoot,
|
||||
{
|
||||
tmpl: '',
|
||||
type: options.mfeType,
|
||||
type: options.mfType,
|
||||
name: options.appName,
|
||||
remotes: remotesWithPorts ?? [],
|
||||
projectRoot: appRoot,
|
||||
@ -1,13 +1,12 @@
|
||||
import type { Tree } from '@nrwl/devkit';
|
||||
import type { Schema } from '../schema';
|
||||
|
||||
import { readProjectConfiguration } from '@nrwl/devkit';
|
||||
import type { Schema } from '../schema';
|
||||
|
||||
export function getRemotesWithPorts(host: Tree, options: Schema) {
|
||||
// If type is host and remotes supplied, check remotes exist
|
||||
const remotesWithPort: { remoteName: string; port: number }[] = [];
|
||||
if (
|
||||
options.mfeType === 'host' &&
|
||||
options.mfType === 'host' &&
|
||||
Array.isArray(options.remotes) &&
|
||||
options.remotes.length > 0
|
||||
) {
|
||||
@ -1,10 +1,9 @@
|
||||
import type { Tree } from '@nrwl/devkit';
|
||||
import { joinPathFragments, readProjectConfiguration } from '@nrwl/devkit';
|
||||
import type { Schema } from '../schema';
|
||||
|
||||
import { readProjectConfiguration, joinPathFragments } from '@nrwl/devkit';
|
||||
|
||||
export function setupHostIfDynamic(tree: Tree, options: Schema) {
|
||||
if (options.federationType === 'static' || options.mfeType === 'remote') {
|
||||
if (options.federationType === 'static' || options.mfType === 'remote') {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1,10 +1,9 @@
|
||||
import type { Tree } from '@nrwl/devkit';
|
||||
import type { Schema } from '../schema';
|
||||
|
||||
import {
|
||||
readProjectConfiguration,
|
||||
updateProjectConfiguration,
|
||||
} from '@nrwl/devkit';
|
||||
import type { Schema } from '../schema';
|
||||
|
||||
export function setupServeTarget(host: Tree, options: Schema) {
|
||||
const appConfig = readProjectConfiguration(host, options.appName);
|
||||
@ -12,7 +11,7 @@ export function setupServeTarget(host: Tree, options: Schema) {
|
||||
appConfig.targets['serve'] = {
|
||||
...appConfig.targets['serve'],
|
||||
executor:
|
||||
options.mfeType === 'host'
|
||||
options.mfType === 'host'
|
||||
? '@nrwl/angular:module-federation-dev-server'
|
||||
: '@nrwl/angular:webpack-server',
|
||||
options: {
|
||||
@ -22,7 +21,7 @@ export function setupServeTarget(host: Tree, options: Schema) {
|
||||
},
|
||||
};
|
||||
|
||||
if (options.mfeType === 'remote') {
|
||||
if (options.mfType === 'remote') {
|
||||
appConfig.targets['serve-static'] = {
|
||||
executor: '@nrwl/angular:file-server',
|
||||
defaultConfiguration: 'development',
|
||||
@ -1,6 +1,6 @@
|
||||
export interface Schema {
|
||||
appName: string;
|
||||
mfeType: 'host' | 'remote';
|
||||
mfType: 'host' | 'remote';
|
||||
port?: number;
|
||||
remotes?: string[];
|
||||
host?: string;
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/schema",
|
||||
"$id": "GeneratorAngularMFESetup",
|
||||
"$id": "GeneratorAngularMFSetup",
|
||||
"cli": "nx",
|
||||
"title": "Generate Module Federation Setup for Angular App",
|
||||
"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?"
|
||||
},
|
||||
"mfeType": {
|
||||
"mfType": {
|
||||
"type": "string",
|
||||
"enum": ["host", "remote"],
|
||||
"description": "Type of application to generate the Module Federation configuration for.",
|
||||
@ -61,6 +61,6 @@
|
||||
"description": "The prefix to use for any generated component."
|
||||
}
|
||||
},
|
||||
"required": ["appName", "mfeType"],
|
||||
"required": ["appName", "mfType"],
|
||||
"additionalProperties": false
|
||||
}
|
||||
@ -0,0 +1,4 @@
|
||||
import { convertNxGenerator } from '@nrwl/devkit';
|
||||
import { setupMf } from './setup-mf';
|
||||
|
||||
export default convertNxGenerator(setupMf);
|
||||
@ -1,10 +1,10 @@
|
||||
import { readJson, Tree } from '@nrwl/devkit';
|
||||
import { readProjectConfiguration } from '@nrwl/devkit';
|
||||
import { readJson, readProjectConfiguration, Tree } from '@nrwl/devkit';
|
||||
import { createTreeWithEmptyWorkspace } from '@nrwl/devkit/testing';
|
||||
|
||||
import { setupMfe } from './setup-mfe';
|
||||
import { setupMf } from './setup-mf';
|
||||
import applicationGenerator from '../application/application';
|
||||
describe('Init MFE', () => {
|
||||
|
||||
describe('Init MF', () => {
|
||||
let tree: Tree;
|
||||
|
||||
beforeEach(async () => {
|
||||
@ -23,12 +23,12 @@ describe('Init MFE', () => {
|
||||
['app1', 'host'],
|
||||
['remote1', 'remote'],
|
||||
])(
|
||||
'should create webpack and mfe configs correctly',
|
||||
'should create webpack and mf configs correctly',
|
||||
async (app, type: 'host' | 'remote') => {
|
||||
// ACT
|
||||
await setupMfe(tree, {
|
||||
await setupMf(tree, {
|
||||
appName: app,
|
||||
mfeType: type,
|
||||
mfType: type,
|
||||
});
|
||||
|
||||
// ASSERT
|
||||
@ -44,11 +44,11 @@ describe('Init MFE', () => {
|
||||
);
|
||||
expect(webpackContents).toMatchSnapshot();
|
||||
|
||||
const mfeConfigContents = tree.read(
|
||||
const mfConfigContents = tree.read(
|
||||
`apps/${app}/module-federation.config.js`,
|
||||
'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');
|
||||
|
||||
// ACT
|
||||
await setupMfe(tree, {
|
||||
await setupMf(tree, {
|
||||
appName: app,
|
||||
mfeType: type,
|
||||
mfType: type,
|
||||
});
|
||||
|
||||
// ASSERT
|
||||
@ -89,9 +89,9 @@ describe('Init MFE', () => {
|
||||
const mainContents = tree.read(`apps/${app}/src/main.ts`, 'utf-8');
|
||||
|
||||
// ACT
|
||||
await setupMfe(tree, {
|
||||
await setupMf(tree, {
|
||||
appName: app,
|
||||
mfeType: type,
|
||||
mfType: type,
|
||||
});
|
||||
|
||||
// ASSERT
|
||||
@ -111,9 +111,9 @@ describe('Init MFE', () => {
|
||||
'should change the build and serve target and set correct path to webpack config',
|
||||
async (app, type: 'host' | 'remote') => {
|
||||
// ACT
|
||||
await setupMfe(tree, {
|
||||
await setupMf(tree, {
|
||||
appName: app,
|
||||
mfeType: type,
|
||||
mfType: type,
|
||||
});
|
||||
|
||||
// ASSERT
|
||||
@ -133,9 +133,9 @@ describe('Init MFE', () => {
|
||||
|
||||
it('should generate the remote entry module and component correctly', async () => {
|
||||
// ACT
|
||||
await setupMfe(tree, {
|
||||
await setupMf(tree, {
|
||||
appName: 'remote1',
|
||||
mfeType: 'remote',
|
||||
mfType: 'remote',
|
||||
prefix: 'my-org',
|
||||
});
|
||||
|
||||
@ -150,7 +150,7 @@ describe('Init MFE', () => {
|
||||
|
||||
it('should generate the remote entry component correctly when prefix is not provided', async () => {
|
||||
// ACT
|
||||
await setupMfe(tree, { appName: 'remote1', mfeType: 'remote' });
|
||||
await setupMf(tree, { appName: 'remote1', mfType: 'remote' });
|
||||
|
||||
// ASSERT
|
||||
expect(
|
||||
@ -160,41 +160,41 @@ describe('Init MFE', () => {
|
||||
|
||||
it('should add the remote config to the host when --remotes flag supplied', async () => {
|
||||
// ACT
|
||||
await setupMfe(tree, {
|
||||
await setupMf(tree, {
|
||||
appName: 'app1',
|
||||
mfeType: 'host',
|
||||
mfType: 'host',
|
||||
remotes: ['remote1'],
|
||||
});
|
||||
|
||||
// ASSERT
|
||||
const mfeConfigContents = tree.read(
|
||||
const mfConfigContents = tree.read(
|
||||
`apps/app1/module-federation.config.js`,
|
||||
'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 () => {
|
||||
// ARRANGE
|
||||
await setupMfe(tree, {
|
||||
await setupMf(tree, {
|
||||
appName: 'app1',
|
||||
mfeType: 'host',
|
||||
mfType: 'host',
|
||||
});
|
||||
|
||||
// ACT
|
||||
await setupMfe(tree, {
|
||||
await setupMf(tree, {
|
||||
appName: 'remote1',
|
||||
mfeType: 'remote',
|
||||
mfType: 'remote',
|
||||
host: 'app1',
|
||||
});
|
||||
|
||||
// ASSERT
|
||||
const hostMfeConfig = tree.read(
|
||||
const hostMfConfig = tree.read(
|
||||
'apps/app1/module-federation.config.js',
|
||||
'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 () => {
|
||||
@ -203,32 +203,32 @@ describe('Init MFE', () => {
|
||||
name: 'remote2',
|
||||
});
|
||||
|
||||
await setupMfe(tree, {
|
||||
await setupMf(tree, {
|
||||
appName: 'app1',
|
||||
mfeType: 'host',
|
||||
mfType: 'host',
|
||||
});
|
||||
|
||||
await setupMfe(tree, {
|
||||
await setupMf(tree, {
|
||||
appName: 'remote1',
|
||||
mfeType: 'remote',
|
||||
mfType: 'remote',
|
||||
host: 'app1',
|
||||
port: 4201,
|
||||
});
|
||||
|
||||
// ACT
|
||||
await setupMfe(tree, {
|
||||
await setupMf(tree, {
|
||||
appName: 'remote2',
|
||||
mfeType: 'remote',
|
||||
mfType: 'remote',
|
||||
host: 'app1',
|
||||
port: 4202,
|
||||
});
|
||||
|
||||
// ASSERT
|
||||
const hostMfeConfig = tree.read(
|
||||
const hostMfConfig = tree.read(
|
||||
'apps/app1/module-federation.config.js',
|
||||
'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 () => {
|
||||
@ -238,24 +238,24 @@ describe('Init MFE', () => {
|
||||
routing: true,
|
||||
});
|
||||
|
||||
await setupMfe(tree, {
|
||||
await setupMf(tree, {
|
||||
appName: 'app1',
|
||||
mfeType: 'host',
|
||||
mfType: 'host',
|
||||
routing: true,
|
||||
});
|
||||
|
||||
await setupMfe(tree, {
|
||||
await setupMf(tree, {
|
||||
appName: 'remote1',
|
||||
mfeType: 'remote',
|
||||
mfType: 'remote',
|
||||
host: 'app1',
|
||||
port: 4201,
|
||||
routing: true,
|
||||
});
|
||||
|
||||
// ACT
|
||||
await setupMfe(tree, {
|
||||
await setupMf(tree, {
|
||||
appName: 'remote2',
|
||||
mfeType: 'remote',
|
||||
mfType: 'remote',
|
||||
host: 'app1',
|
||||
port: 4202,
|
||||
routing: true,
|
||||
@ -274,9 +274,9 @@ describe('Init MFE', () => {
|
||||
});
|
||||
|
||||
// ACT
|
||||
await setupMfe(tree, {
|
||||
await setupMf(tree, {
|
||||
appName: 'test-app',
|
||||
mfeType: 'host',
|
||||
mfType: 'host',
|
||||
routing: true,
|
||||
});
|
||||
|
||||
@ -293,9 +293,9 @@ describe('Init MFE', () => {
|
||||
describe('--federationType=dynamic', () => {
|
||||
it('should create a host with the correct configurations', async () => {
|
||||
// ARRANGE & ACT
|
||||
await setupMfe(tree, {
|
||||
await setupMf(tree, {
|
||||
appName: 'app1',
|
||||
mfeType: 'host',
|
||||
mfType: 'host',
|
||||
routing: true,
|
||||
federationType: 'dynamic',
|
||||
});
|
||||
@ -313,17 +313,17 @@ describe('Init MFE', () => {
|
||||
|
||||
it('should add a remote to dynamic host correctly', async () => {
|
||||
// ARRANGE
|
||||
await setupMfe(tree, {
|
||||
await setupMf(tree, {
|
||||
appName: 'app1',
|
||||
mfeType: 'host',
|
||||
mfType: 'host',
|
||||
routing: true,
|
||||
federationType: 'dynamic',
|
||||
});
|
||||
|
||||
// ACT
|
||||
await setupMfe(tree, {
|
||||
await setupMf(tree, {
|
||||
appName: 'remote1',
|
||||
mfeType: 'remote',
|
||||
mfType: 'remote',
|
||||
port: 4201,
|
||||
host: 'app1',
|
||||
routing: true,
|
||||
@ -1,8 +1,7 @@
|
||||
import type { Tree } from '@nrwl/devkit';
|
||||
import { formatFiles, readProjectConfiguration } from '@nrwl/devkit';
|
||||
import type { Schema } from './schema';
|
||||
|
||||
import { readProjectConfiguration, formatFiles } from '@nrwl/devkit';
|
||||
|
||||
import {
|
||||
addCypressOnErrorWorkaround,
|
||||
addEntryModule,
|
||||
@ -11,12 +10,12 @@ import {
|
||||
fixBootstrap,
|
||||
generateWebpackConfig,
|
||||
getRemotesWithPorts,
|
||||
setupServeTarget,
|
||||
setupHostIfDynamic,
|
||||
setupServeTarget,
|
||||
updateTsConfigTarget,
|
||||
} from './lib';
|
||||
|
||||
export async function setupMfe(tree: Tree, options: Schema) {
|
||||
export async function setupMf(tree: Tree, options: Schema) {
|
||||
const projectConfig = readProjectConfiguration(tree, options.appName);
|
||||
|
||||
options.federationType = options.federationType ?? 'static';
|
||||
@ -43,4 +42,4 @@ export async function setupMfe(tree: Tree, options: Schema) {
|
||||
}
|
||||
}
|
||||
|
||||
export default setupMfe;
|
||||
export default setupMf;
|
||||
@ -1,4 +0,0 @@
|
||||
import { convertNxGenerator } from '@nrwl/devkit';
|
||||
import { setupMfe } from './setup-mfe';
|
||||
|
||||
export default convertNxGenerator(setupMfe);
|
||||
@ -1,8 +1,8 @@
|
||||
import { removeProjectConfiguration, Tree } from '@nrwl/devkit';
|
||||
import { removeProjectConfiguration } from '@nrwl/devkit';
|
||||
import { createTreeWithEmptyWorkspace } from '@nrwl/devkit/testing';
|
||||
import applicationGenerator from '../../generators/application/application';
|
||||
import setupMfe from '../../generators/setup-mfe/setup-mfe';
|
||||
import addCypressMfeWorkaround from './add-cypress-mfe-workaround';
|
||||
import setupMf from '../../generators/setup-mf/setup-mf';
|
||||
import addCypressMfWorkaround from './add-cypress-mf-workaround';
|
||||
|
||||
describe('Add Cypress MFE Workaround', () => {
|
||||
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,
|
||||
});
|
||||
|
||||
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', '');
|
||||
|
||||
// ACT
|
||||
await addCypressMfeWorkaround(tree);
|
||||
await addCypressMfWorkaround(tree);
|
||||
|
||||
// ASSERT
|
||||
expect(tree.read('apps/app1-e2e/src/support/index.ts', 'utf-8')).toContain(
|
||||
@ -34,13 +34,13 @@ describe('Add Cypress MFE Workaround', () => {
|
||||
routing: true,
|
||||
});
|
||||
|
||||
await setupMfe(tree, { appName: 'app1', mfeType: 'host', routing: true });
|
||||
await setupMf(tree, { appName: 'app1', mfType: 'host', routing: true });
|
||||
|
||||
removeProjectConfiguration(tree, 'app1-e2e');
|
||||
tree.delete('apps/app1-e2e');
|
||||
|
||||
// ACT
|
||||
await addCypressMfeWorkaround(tree);
|
||||
await addCypressMfWorkaround(tree);
|
||||
|
||||
// ASSERT
|
||||
expect(tree.exists('apps/app1-e2e/src/support/index.ts')).toBeFalsy();
|
||||
@ -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'
|
||||
})
|
||||
|
||||
};
|
||||
"
|
||||
`);
|
||||
});
|
||||
});
|
||||
@ -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);
|
||||
});
|
||||
}
|
||||
@ -4,9 +4,9 @@ import * as fs from 'fs';
|
||||
import * as tsUtils from '@nrwl/workspace/src/utilities/typescript';
|
||||
|
||||
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());
|
||||
|
||||
describe('ShareWorkspaceLibraries', () => {
|
||||
@ -20,7 +20,7 @@ describe('MFE Webpack Utils', () => {
|
||||
} catch (error) {
|
||||
// ASSERT
|
||||
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) {
|
||||
// ASSERT
|
||||
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.'
|
||||
);
|
||||
}
|
||||
});
|
||||
@ -87,7 +87,7 @@ export function shareWorkspaceLibraries(
|
||||
) {
|
||||
if (!existsSync(tsConfigPath)) {
|
||||
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})`
|
||||
);
|
||||
}
|
||||
|
||||
@ -8,7 +8,7 @@ export function readRootPackageJson(): {
|
||||
const pkgJsonPath = joinPathFragments(workspaceRoot, 'package.json');
|
||||
if (!existsSync(pkgJsonPath)) {
|
||||
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.'
|
||||
);
|
||||
}
|
||||
|
||||
@ -3,7 +3,7 @@ import {
|
||||
SharedLibraryConfig,
|
||||
sharePackages,
|
||||
shareWorkspaceLibraries,
|
||||
} from './mfe-webpack';
|
||||
} from './mf-webpack';
|
||||
import {
|
||||
createProjectGraphAsync,
|
||||
ProjectGraph,
|
||||
@ -16,10 +16,10 @@ import {
|
||||
import { ParsedCommandLine } from 'typescript';
|
||||
import { readRootPackageJson } from './utils';
|
||||
import { extname, join } from 'path';
|
||||
import ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin');
|
||||
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 = (
|
||||
libraryName: string,
|
||||
@ -31,9 +31,9 @@ type AdditionalSharedConfig = Array<
|
||||
| { libraryName: string; sharedConfig: SharedLibraryConfig }
|
||||
>;
|
||||
|
||||
export interface MFEConfig {
|
||||
export interface MFConfig {
|
||||
name: string;
|
||||
remotes?: MFERemotes;
|
||||
remotes?: MFRemotes;
|
||||
exposes?: Record<string, string>;
|
||||
shared?: SharedFunction;
|
||||
additionalShared?: AdditionalSharedConfig;
|
||||
@ -134,7 +134,7 @@ function determineRemoteUrl(remote: string) {
|
||||
}/remoteEntry.mjs`;
|
||||
}
|
||||
|
||||
function mapRemotes(remotes: MFERemotes) {
|
||||
function mapRemotes(remotes: MFRemotes) {
|
||||
const mappedRemotes = {};
|
||||
|
||||
for (const remote of remotes) {
|
||||
@ -233,8 +233,8 @@ function applyDefaultEagerPackages(
|
||||
}
|
||||
}
|
||||
|
||||
export async function withModuleFederation(options: MFEConfig) {
|
||||
const DEFAULT_NPM_PACKAGES_TO_AVOID = ['zone.js', '@nrwl/angular/mfe'];
|
||||
export async function withModuleFederation(options: MFConfig) {
|
||||
const DEFAULT_NPM_PACKAGES_TO_AVOID = ['zone.js', '@nrwl/angular/mf'];
|
||||
|
||||
let projectGraph: ProjectGraph<any>;
|
||||
try {
|
||||
Loading…
x
Reference in New Issue
Block a user