Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(angular): add mfe-host generator (#9218)
- Loading branch information
Showing
11 changed files
with
400 additions
and
1 deletion.
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-host generator' | ||
description: 'Generate a Host Angular Micro Frontend Application.' | ||
--- | ||
|
||
# @nrwl/angular:mfe-host | ||
|
||
Generate a Host Angular Micro Frontend Application. | ||
|
||
## Usage | ||
|
||
```bash | ||
nx generate mfe-host ... | ||
``` | ||
|
||
```bash | ||
nx g host ... # same | ||
``` | ||
|
||
By default, Nx will search for `mfe-host` in the default collection provisioned in `workspace.json`. | ||
|
||
You can specify the collection explicitly as follows: | ||
|
||
```bash | ||
nx g @nrwl/angular:mfe-host ... | ||
``` | ||
|
||
Show what will be generated without writing to disk: | ||
|
||
```bash | ||
nx g mfe-host ... --dry-run | ||
``` | ||
|
||
### Examples | ||
|
||
Create an Angular app with configuration in place for MFE. If remotes is provided, attach the remote app to this app's configuration.: | ||
|
||
```bash | ||
nx g @nrwl/angular:mfe-host appName --remotes=remote1 | ||
``` | ||
|
||
## Options | ||
|
||
### name (_**required**_) | ||
|
||
Type: `string` | ||
|
||
The name to give to the host Angular app. | ||
|
||
### host | ||
|
||
Type: `string` | ||
|
||
The name of the host app to attach this host 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
189 changes: 189 additions & 0 deletions
189
packages/angular/src/generators/mfe-host/__snapshots__/mfe-host.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,189 @@ | ||
// Jest Snapshot v1, https://goo.gl/fbAQLP | ||
|
||
exports[`MFE Host App Generator should generate a host mfe app with a remote 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: \\"remote\\", | ||
publicPath: \\"auto\\", | ||
}, | ||
optimization: { | ||
runtimeChunk: false, | ||
}, | ||
experiments: { | ||
outputModule: true | ||
}, | ||
resolve: { | ||
alias: { | ||
...sharedMappings.getAliases(), | ||
}, | ||
}, | ||
plugins: [ | ||
new ModuleFederationPlugin({ | ||
name: \\"remote\\", | ||
filename: \\"remoteEntry.js\\", | ||
exposes: { | ||
'./Module': 'apps/remote/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 Host App Generator should generate a host mfe app with a remote 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({ | ||
remotes: { | ||
\\"remote\\": \\"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 Host App Generator should generate a host mfe app with no remotes 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({ | ||
remotes: { | ||
}, | ||
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(), | ||
], | ||
}; | ||
" | ||
`; |
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 mfeHost from './mfe-host'; | ||
|
||
export default convertNxGenerator(mfeHost); |
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 mfeHost from './mfe-host'; | ||
import applicationGenerator from '../application/application'; | ||
|
||
describe('MFE Host App Generator', () => { | ||
it('should generate a host mfe app with no remotes', async () => { | ||
// ARRANGE | ||
const tree = createTreeWithEmptyWorkspace(2); | ||
|
||
// ACT | ||
await mfeHost(tree, { | ||
name: 'test', | ||
}); | ||
|
||
// ASSERT | ||
expect(tree.read('apps/test/webpack.config.js', 'utf-8')).toMatchSnapshot(); | ||
}); | ||
|
||
it('should generate a host mfe app with a remote', async () => { | ||
// ARRANGE | ||
const tree = createTreeWithEmptyWorkspace(2); | ||
|
||
await applicationGenerator(tree, { | ||
name: 'remote', | ||
mfe: true, | ||
mfeType: 'remote', | ||
routing: true, | ||
port: 4201, | ||
}); | ||
|
||
// ACT | ||
await mfeHost(tree, { | ||
name: 'test', | ||
remotes: ['remote'], | ||
}); | ||
|
||
// ASSERT | ||
expect( | ||
tree.read('apps/remote/webpack.config.js', 'utf-8') | ||
).toMatchSnapshot(); | ||
expect(tree.read('apps/test/webpack.config.js', 'utf-8')).toMatchSnapshot(); | ||
}); | ||
|
||
it('should error when a host app is attempted to be generated with an incorrect remote', async () => { | ||
// ARRANGE | ||
const tree = createTreeWithEmptyWorkspace(2); | ||
|
||
// ACT | ||
try { | ||
await mfeHost(tree, { | ||
name: 'test', | ||
remotes: ['remote'], | ||
}); | ||
} catch (error) { | ||
// ASSERT | ||
expect(error.message).toEqual( | ||
'Could not find specified remote application (remote)' | ||
); | ||
} | ||
}); | ||
}); |
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,30 @@ | ||
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 mfeHost(tree: Tree, options: Schema) { | ||
const projects = getProjects(tree); | ||
|
||
if (options.remotes && options.remotes.length > 0) { | ||
options.remotes.forEach((remote) => { | ||
if (!projects.has(remote)) { | ||
throw new Error( | ||
`Could not find specified remote application (${remote})` | ||
); | ||
} | ||
}); | ||
} | ||
|
||
const installTask = await applicationGenerator(tree, { | ||
name: options.name, | ||
mfe: true, | ||
mfeType: 'host', | ||
routing: true, | ||
remotes: options.remotes ?? [], | ||
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,4 @@ | ||
export interface Schema { | ||
name: string; | ||
remotes?: string[]; | ||
} |
Oops, something went wrong.
7442030
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: