Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
feat(angular): add mfe-remote generator (#9191)
- Loading branch information
Showing
10 changed files
with
397 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
--- | ||
title: '@nrwl/angular:mfe-remote generator' | ||
description: 'Generate a Remote Angular Micro-Frontend Application.' | ||
--- | ||
|
||
# @nrwl/angular:mfe-remote | ||
|
||
Generate a Remote Angular Micro-Frontend Application. | ||
|
||
## Usage | ||
|
||
```bash | ||
nx generate mfe-remote ... | ||
``` | ||
|
||
```bash | ||
nx g remote ... # same | ||
``` | ||
|
||
By default, Nx will search for `mfe-remote` in the default collection provisioned in `workspace.json`. | ||
|
||
You can specify the collection explicitly as follows: | ||
|
||
```bash | ||
nx g @nrwl/angular:mfe-remote ... | ||
``` | ||
|
||
Show what will be generated without writing to disk: | ||
|
||
```bash | ||
nx g mfe-remote ... --dry-run | ||
``` | ||
|
||
### Examples | ||
|
||
Create an Angular app with configuration in place for MFE. If host is provided, attach this remote app to host app's configuration.: | ||
|
||
```bash | ||
nx g @nrwl/angular:mfe-remote appName --host=host --port=4201 | ||
``` | ||
|
||
## Options | ||
|
||
### name (_**required**_) | ||
|
||
Type: `string` | ||
|
||
The name to give to the remote Angular app. | ||
|
||
### host | ||
|
||
Type: `string` | ||
|
||
The name of the host app to attach this remote app to. | ||
|
||
### port | ||
|
||
Type: `string` | ||
|
||
The port on which this app should be served. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
192 changes: 192 additions & 0 deletions
192
packages/angular/src/generators/mfe-remote/__snapshots__/mfe-remote.spec.ts.snap
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,192 @@ | ||
// Jest Snapshot v1, https://goo.gl/fbAQLP | ||
|
||
exports[`MFE Remote App Generator should generate a remote mfe app with a host 1`] = ` | ||
"const ModuleFederationPlugin = require(\\"webpack/lib/container/ModuleFederationPlugin\\"); | ||
const mf = require(\\"@angular-architects/module-federation/webpack\\"); | ||
const path = require(\\"path\\"); | ||
const share = mf.share; | ||
/** | ||
* We use the NX_TSCONFIG_PATH environment variable when using the @nrwl/angular:webpack-browser | ||
* builder as it will generate a temporary tsconfig file which contains any required remappings of | ||
* shared libraries. | ||
* A remapping will occur when a library is buildable, as webpack needs to know the location of the | ||
* built files for the buildable library. | ||
* This NX_TSCONFIG_PATH environment variable is set by the @nrwl/angular:webpack-browser and it contains | ||
* the location of the generated temporary tsconfig file. | ||
*/ | ||
const tsConfigPath = process.env.NX_TSCONFIG_PATH ?? path.join(__dirname, '../../tsconfig.base.json'); | ||
const workspaceRootPath = path.join(__dirname, '../../'); | ||
const sharedMappings = new mf.SharedMappings(); | ||
sharedMappings.register(tsConfigPath, [ | ||
/* mapped paths to share */ | ||
], workspaceRootPath); | ||
module.exports = { | ||
output: { | ||
uniqueName: \\"host\\", | ||
publicPath: \\"auto\\", | ||
}, | ||
optimization: { | ||
runtimeChunk: false, | ||
}, | ||
experiments: { | ||
outputModule: true | ||
}, | ||
resolve: { | ||
alias: { | ||
...sharedMappings.getAliases(), | ||
}, | ||
}, | ||
plugins: [ | ||
new ModuleFederationPlugin({ | ||
remotes: { | ||
\\"test\\": 'http://localhost:4201/remoteEntry.js', | ||
}, | ||
shared: share({ | ||
\\"@angular/core\\": { singleton: true, strictVersion: true, requiredVersion: 'auto', includeSecondaries: true }, | ||
\\"@angular/common\\": { singleton: true, strictVersion: true, requiredVersion: 'auto', includeSecondaries: true }, | ||
\\"@angular/common/http\\": { singleton: true, strictVersion: true, requiredVersion: 'auto', includeSecondaries: true }, | ||
\\"@angular/router\\": { singleton: true, strictVersion: true, requiredVersion: 'auto', includeSecondaries: true }, | ||
\\"rxjs\\": { singleton: true, strictVersion: true, requiredVersion: 'auto', includeSecondaries: true }, | ||
...sharedMappings.getDescriptors(), | ||
}), | ||
library: { | ||
type: 'module' | ||
}, | ||
}), | ||
sharedMappings.getPlugin(), | ||
], | ||
}; | ||
" | ||
`; | ||
|
||
exports[`MFE Remote App Generator should generate a remote mfe app with a host 2`] = ` | ||
"const ModuleFederationPlugin = require(\\"webpack/lib/container/ModuleFederationPlugin\\"); | ||
const mf = require(\\"@angular-architects/module-federation/webpack\\"); | ||
const path = require(\\"path\\"); | ||
const share = mf.share; | ||
/** | ||
* We use the NX_TSCONFIG_PATH environment variable when using the @nrwl/angular:webpack-browser | ||
* builder as it will generate a temporary tsconfig file which contains any required remappings of | ||
* shared libraries. | ||
* A remapping will occur when a library is buildable, as webpack needs to know the location of the | ||
* built files for the buildable library. | ||
* This NX_TSCONFIG_PATH environment variable is set by the @nrwl/angular:webpack-browser and it contains | ||
* the location of the generated temporary tsconfig file. | ||
*/ | ||
const tsConfigPath = process.env.NX_TSCONFIG_PATH ?? path.join(__dirname, '../../tsconfig.base.json'); | ||
const workspaceRootPath = path.join(__dirname, '../../'); | ||
const sharedMappings = new mf.SharedMappings(); | ||
sharedMappings.register(tsConfigPath, [ | ||
/* mapped paths to share */ | ||
], workspaceRootPath); | ||
module.exports = { | ||
output: { | ||
uniqueName: \\"test\\", | ||
publicPath: \\"auto\\", | ||
}, | ||
optimization: { | ||
runtimeChunk: false, | ||
}, | ||
experiments: { | ||
outputModule: true | ||
}, | ||
resolve: { | ||
alias: { | ||
...sharedMappings.getAliases(), | ||
}, | ||
}, | ||
plugins: [ | ||
new ModuleFederationPlugin({ | ||
name: \\"test\\", | ||
filename: \\"remoteEntry.js\\", | ||
exposes: { | ||
'./Module': 'apps/test/src/app/remote-entry/entry.module.ts', | ||
}, | ||
shared: share({ | ||
\\"@angular/core\\": { singleton: true, strictVersion: true, requiredVersion: 'auto', includeSecondaries: true }, | ||
\\"@angular/common\\": { singleton: true, strictVersion: true, requiredVersion: 'auto', includeSecondaries: true }, | ||
\\"@angular/common/http\\": { singleton: true, strictVersion: true, requiredVersion: 'auto', includeSecondaries: true }, | ||
\\"@angular/router\\": { singleton: true, strictVersion: true, requiredVersion: 'auto', includeSecondaries: true }, | ||
\\"rxjs\\": { singleton: true, strictVersion: true, requiredVersion: 'auto', includeSecondaries: true }, | ||
...sharedMappings.getDescriptors(), | ||
}), | ||
library: { | ||
type: 'module' | ||
}, | ||
}), | ||
sharedMappings.getPlugin(), | ||
], | ||
}; | ||
" | ||
`; | ||
|
||
exports[`MFE Remote App Generator should generate a remote mfe app with no host 1`] = ` | ||
"const ModuleFederationPlugin = require(\\"webpack/lib/container/ModuleFederationPlugin\\"); | ||
const mf = require(\\"@angular-architects/module-federation/webpack\\"); | ||
const path = require(\\"path\\"); | ||
const share = mf.share; | ||
/** | ||
* We use the NX_TSCONFIG_PATH environment variable when using the @nrwl/angular:webpack-browser | ||
* builder as it will generate a temporary tsconfig file which contains any required remappings of | ||
* shared libraries. | ||
* A remapping will occur when a library is buildable, as webpack needs to know the location of the | ||
* built files for the buildable library. | ||
* This NX_TSCONFIG_PATH environment variable is set by the @nrwl/angular:webpack-browser and it contains | ||
* the location of the generated temporary tsconfig file. | ||
*/ | ||
const tsConfigPath = process.env.NX_TSCONFIG_PATH ?? path.join(__dirname, '../../tsconfig.base.json'); | ||
const workspaceRootPath = path.join(__dirname, '../../'); | ||
const sharedMappings = new mf.SharedMappings(); | ||
sharedMappings.register(tsConfigPath, [ | ||
/* mapped paths to share */ | ||
], workspaceRootPath); | ||
module.exports = { | ||
output: { | ||
uniqueName: \\"test\\", | ||
publicPath: \\"auto\\", | ||
}, | ||
optimization: { | ||
runtimeChunk: false, | ||
}, | ||
experiments: { | ||
outputModule: true | ||
}, | ||
resolve: { | ||
alias: { | ||
...sharedMappings.getAliases(), | ||
}, | ||
}, | ||
plugins: [ | ||
new ModuleFederationPlugin({ | ||
name: \\"test\\", | ||
filename: \\"remoteEntry.js\\", | ||
exposes: { | ||
'./Module': 'apps/test/src/app/remote-entry/entry.module.ts', | ||
}, | ||
shared: share({ | ||
\\"@angular/core\\": { singleton: true, strictVersion: true, requiredVersion: 'auto', includeSecondaries: true }, | ||
\\"@angular/common\\": { singleton: true, strictVersion: true, requiredVersion: 'auto', includeSecondaries: true }, | ||
\\"@angular/common/http\\": { singleton: true, strictVersion: true, requiredVersion: 'auto', includeSecondaries: true }, | ||
\\"@angular/router\\": { singleton: true, strictVersion: true, requiredVersion: 'auto', includeSecondaries: true }, | ||
\\"rxjs\\": { singleton: true, strictVersion: true, requiredVersion: 'auto', includeSecondaries: true }, | ||
...sharedMappings.getDescriptors(), | ||
}), | ||
library: { | ||
type: 'module' | ||
}, | ||
}), | ||
sharedMappings.getPlugin(), | ||
], | ||
}; | ||
" | ||
`; |
4 changes: 4 additions & 0 deletions
4
packages/angular/src/generators/mfe-remote/mfe-remote.compat.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
import { convertNxGenerator } from '@nrwl/devkit'; | ||
import mfeRemote from './mfe-remote'; | ||
|
||
export default convertNxGenerator(mfeRemote); |
61 changes: 61 additions & 0 deletions
61
packages/angular/src/generators/mfe-remote/mfe-remote.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
import { createTreeWithEmptyWorkspace } from '@nrwl/devkit/testing'; | ||
import mfeRemote from './mfe-remote'; | ||
import applicationGenerator from '../application/application'; | ||
|
||
describe('MFE Remote App Generator', () => { | ||
it('should generate a remote mfe app with no host', async () => { | ||
// ARRANGE | ||
const tree = createTreeWithEmptyWorkspace(2); | ||
|
||
// ACT | ||
await mfeRemote(tree, { | ||
name: 'test', | ||
port: 4201, | ||
}); | ||
|
||
// ASSERT | ||
expect(tree.read('apps/test/webpack.config.js', 'utf-8')).toMatchSnapshot(); | ||
}); | ||
|
||
it('should generate a remote mfe app with a host', async () => { | ||
// ARRANGE | ||
const tree = createTreeWithEmptyWorkspace(2); | ||
|
||
await applicationGenerator(tree, { | ||
name: 'host', | ||
mfe: true, | ||
mfeType: 'host', | ||
routing: true, | ||
}); | ||
|
||
// ACT | ||
await mfeRemote(tree, { | ||
name: 'test', | ||
host: 'host', | ||
port: 4201, | ||
}); | ||
|
||
// ASSERT | ||
expect(tree.read('apps/host/webpack.config.js', 'utf-8')).toMatchSnapshot(); | ||
expect(tree.read('apps/test/webpack.config.js', 'utf-8')).toMatchSnapshot(); | ||
}); | ||
|
||
it('should error when a remote app is attempted to be generated with an incorrect host', async () => { | ||
// ARRANGE | ||
const tree = createTreeWithEmptyWorkspace(2); | ||
|
||
// ACT | ||
try { | ||
await mfeRemote(tree, { | ||
name: 'test', | ||
host: 'host', | ||
port: 4201, | ||
}); | ||
} catch (error) { | ||
// ASSERT | ||
expect(error.message).toEqual( | ||
'The name of the application to be used as the host app does not exist. (host)' | ||
); | ||
} | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import type { Tree } from '@nrwl/devkit'; | ||
import type { Schema } from './schema'; | ||
import { getProjects } from '@nrwl/devkit'; | ||
import applicationGenerator from '../application/application'; | ||
|
||
export default async function mfeRemote(tree: Tree, options: Schema) { | ||
const projects = getProjects(tree); | ||
if (options.host && !projects.has(options.host)) { | ||
throw new Error( | ||
`The name of the application to be used as the host app does not exist. (${options.host})` | ||
); | ||
} | ||
|
||
const installTask = await applicationGenerator(tree, { | ||
name: options.name, | ||
mfe: true, | ||
mfeType: 'remote', | ||
routing: true, | ||
host: options.host, | ||
port: options.port ?? 4200, | ||
}); | ||
|
||
return installTask; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
export interface Schema { | ||
name: string; | ||
host?: string; | ||
port?: number; | ||
} |
Oops, something went wrong.
6c99959
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Successfully deployed to the following URLs: