feat(angular): use withModuleFederation for mfe (#9454)

This commit is contained in:
Colum Ferry 2022-03-24 09:27:51 +00:00 committed by GitHub
parent d4b5c30eba
commit 592c3d3541
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 150 additions and 1002 deletions

View File

@ -1,256 +1,37 @@
// 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`] = `
"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: \\"app1\\",
publicPath: \\"auto\\",
},
optimization: {
runtimeChunk: false,
},
experiments: {
outputModule: true
},
resolve: {
alias: {
...sharedMappings.getAliases(),
},
},
plugins: [
new ModuleFederationPlugin({
remotes: {
\\"remote1\\": 'http://localhost:4201/remoteEntry.js',
\\"remote2\\": 'http://localhost:4202/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(),
],
};
"
"const { withModuleFederation } = require('@nrwl/angular/module-federation');
module.exports = withModuleFederation({
name: 'app1',
remotes: ['remote1','remote2',]
});"
`;
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`] = `
"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: \\"app1\\",
publicPath: \\"auto\\",
},
optimization: {
runtimeChunk: false,
},
experiments: {
outputModule: true
},
resolve: {
alias: {
...sharedMappings.getAliases(),
},
},
plugins: [
new ModuleFederationPlugin({
remotes: {
\\"remote1\\": 'http://localhost:4200/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(),
],
};
"
"const { withModuleFederation } = require('@nrwl/angular/module-federation');
module.exports = withModuleFederation({
name: 'app1',
remotes: ['remote1',]
});"
`;
exports[`app --mfe should generate a Module Federation correctly for a each app 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: \\"my-app\\",
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(),
],
};
"
"const { withModuleFederation } = require('@nrwl/angular/module-federation');
module.exports = withModuleFederation({
name: 'my-app',
remotes: []
});"
`;
exports[`app --mfe should generate a Module Federation correctly for a each app 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: \\"my-app\\",
publicPath: \\"auto\\",
"const { withModuleFederation } = require('@nrwl/angular/module-federation');
module.exports = withModuleFederation({
name: 'my-app',
exposes: {
'./Module': 'apps/my-app/src/app/remote-entry/entry.module.ts',
},
optimization: {
runtimeChunk: false,
},
experiments: {
outputModule: true
},
resolve: {
alias: {
...sharedMappings.getAliases(),
},
},
plugins: [
new ModuleFederationPlugin({
name: \\"my-app\\",
filename: \\"remoteEntry.js\\",
exposes: {
'./Module': 'apps/my-app/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[`app at the root should accept numbers in the path 1`] = `"src/9-websites/my-app"`;

View File

@ -1,189 +1,27 @@
// 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\\",
"const { withModuleFederation } = require('@nrwl/angular/module-federation');
module.exports = withModuleFederation({
name: 'remote',
exposes: {
'./Module': 'apps/remote/src/app/remote-entry/entry.module.ts',
},
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(),
],
};
"
"const { withModuleFederation } = require('@nrwl/angular/module-federation');
module.exports = withModuleFederation({
name: 'test',
remotes: ['remote',]
});"
`;
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(),
],
};
"
"const { withModuleFederation } = require('@nrwl/angular/module-federation');
module.exports = withModuleFederation({
name: 'test',
remotes: []
});"
`;

View File

@ -1,192 +1,29 @@
// 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(),
],
};
"
"const { withModuleFederation } = require('@nrwl/angular/module-federation');
module.exports = withModuleFederation({
name: 'host',
remotes: ['test',]
});"
`;
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\\",
"const { withModuleFederation } = require('@nrwl/angular/module-federation');
module.exports = withModuleFederation({
name: 'test',
exposes: {
'./Module': 'apps/test/src/app/remote-entry/entry.module.ts',
},
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\\",
"const { withModuleFederation } = require('@nrwl/angular/module-federation');
module.exports = withModuleFederation({
name: 'test',
exposes: {
'./Module': 'apps/test/src/app/remote-entry/entry.module.ts',
},
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(),
],
};
"
});"
`;

View File

@ -31,254 +31,35 @@ 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`] = `
"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: \\"app1\\",
publicPath: \\"auto\\",
},
optimization: {
runtimeChunk: false,
},
experiments: {
outputModule: true
},
resolve: {
alias: {
...sharedMappings.getAliases(),
},
},
plugins: [
new ModuleFederationPlugin({
remotes: {
\\"remote1\\": 'http://localhost:4201/remoteEntry.js',
\\"remote2\\": 'http://localhost:4202/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(),
],
};
"
"const { withModuleFederation } = require('@nrwl/angular/module-federation');
module.exports = withModuleFederation({
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`] = `
"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: \\"app1\\",
publicPath: \\"auto\\",
},
optimization: {
runtimeChunk: false,
},
experiments: {
outputModule: true
},
resolve: {
alias: {
...sharedMappings.getAliases(),
},
},
plugins: [
new ModuleFederationPlugin({
remotes: {
\\"remote1\\": 'http://localhost:4200/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(),
],
};
"
"const { withModuleFederation } = require('@nrwl/angular/module-federation');
module.exports = withModuleFederation({
name: 'app1',
remotes: ['remote1',]
});"
`;
exports[`Init MFE should create webpack configs correctly 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: \\"app1\\",
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(),
],
};
"
"const { withModuleFederation } = require('@nrwl/angular/module-federation');
module.exports = withModuleFederation({
name: 'app1',
remotes: []
});"
`;
exports[`Init MFE should create webpack configs correctly 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: \\"remote1\\",
publicPath: \\"auto\\",
"const { withModuleFederation } = require('@nrwl/angular/module-federation');
module.exports = withModuleFederation({
name: 'remote1',
exposes: {
'./Module': 'apps/remote1/src/app/remote-entry/entry.module.ts',
},
optimization: {
runtimeChunk: false,
},
experiments: {
outputModule: true
},
resolve: {
alias: {
...sharedMappings.getAliases(),
},
},
plugins: [
new ModuleFederationPlugin({
name: \\"remote1\\",
filename: \\"remoteEntry.js\\",
exposes: {
'./Module': 'apps/remote1/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(),
],
};
"
});"
`;

View File

@ -1,59 +1,8 @@
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, '<%= rootTsConfigPath %>');
const workspaceRootPath = path.join(__dirname, '<%= offsetFromRoot %>');
const sharedMappings = new mf.SharedMappings();
sharedMappings.register(tsConfigPath, [
/* mapped paths to share */
], workspaceRootPath);
module.exports = {
output: {
uniqueName: "<%= name %>",
publicPath: "auto",
},
optimization: {
runtimeChunk: false,
},
experiments: {
outputModule: true
},
resolve: {
alias: {
...sharedMappings.getAliases(),
},
},
plugins: [
new ModuleFederationPlugin({<% if(type === 'remote') { %>
name: "<%= name %>",
filename: "remoteEntry.js",
exposes: {
'./Module': '<%= sourceRoot %>/src/app/remote-entry/entry.module.ts',
},<% } %><% if(type === 'host') { %>
remotes: {
<% remotes.forEach(function(remote) { %>"<%= remote.remoteName %>": "http://localhost:<%= remote.port %>/remoteEntry.js",<% }); %>
},<% } %>
shared: share({<% sharedLibraries.forEach(function (lib) { %>
"<%= lib %>": { singleton: true, strictVersion: true, requiredVersion: 'auto', includeSecondaries: true },<% }); %>
...sharedMappings.getDescriptors(),
}),
library: {
type: 'module'
},
}),
sharedMappings.getPlugin(),
],
};
const { withModuleFederation } = require('@nrwl/angular/module-federation');
module.exports = withModuleFederation({
name: '<%= name %>',<% if(type === 'host') { %>
remotes: [<% remotes.forEach(function(remote) { %>'<%= remote.remoteName %>',<% }); %>]<% } %><% if(type === 'remote') { %>
exposes: {
'./Module': '<%= projectRoot %>/src/app/remote-entry/entry.module.ts',
},<% } %>
});

View File

@ -0,0 +1,10 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Add remote to host should add remote correctly even in multiline 1`] = `
"const obj = {
remotes: [
'remote1',
'remote2',
'remote3',]
}"
`;

View File

@ -0,0 +1,33 @@
import { tsquery } from '@phenomnomnominal/tsquery';
import type { ArrayLiteralExpression } from 'typescript';
import { checkIsCommaNeeded } from './add-remote-to-host';
describe('Add remote to host', () => {
it('should add remote correctly even in multiline', () => {
// ARRANGE
const hostWebpackConfig = `const obj = {
remotes: [
'remote1',
'remote2',
]
}`;
const webpackAst = tsquery.ast(hostWebpackConfig);
const mfRemotesNode = tsquery(
webpackAst,
'Identifier[name=remotes] ~ ArrayLiteralExpression',
{ visitAllChildren: true }
)[0] as ArrayLiteralExpression;
const endOfPropertiesPos = mfRemotesNode.getEnd() - 1;
// ACT
const isCommaNeeded = checkIsCommaNeeded(mfRemotesNode.getText());
const updatedConfig = `${hostWebpackConfig.slice(0, endOfPropertiesPos)}${
isCommaNeeded ? ',' : ''
}'remote3',${hostWebpackConfig.slice(endOfPropertiesPos)}`;
// ASSERT
expect(updatedConfig).toMatchSnapshot();
});
});

View File

@ -3,11 +3,20 @@ import type { Schema } from '../schema';
import { readProjectConfiguration, joinPathFragments } from '@nrwl/devkit';
import { tsquery } from '@phenomnomnominal/tsquery';
import { ObjectLiteralExpression } from 'typescript';
import { ArrayLiteralExpression } from 'typescript';
import { addRoute } from '../../../utils/nx-devkit/ast-utils';
import * as ts from 'typescript';
export function checkIsCommaNeeded(mfeRemoteText: string) {
const remoteText = mfeRemoteText.replace(/\s+/g, '');
return !remoteText.endsWith(',]')
? remoteText === '[]'
? false
: true
: false;
}
export function addRemoteToHost(host: Tree, options: Schema) {
if (options.mfeType === 'remote' && options.host) {
const hostProject = readProjectConfiguration(host, options.host);
@ -24,16 +33,16 @@ export function addRemoteToHost(host: Tree, options: Schema) {
const webpackAst = tsquery.ast(hostWebpackConfig);
const mfRemotesNode = tsquery(
webpackAst,
'Identifier[name=remotes] ~ ObjectLiteralExpression',
'Identifier[name=remotes] ~ ArrayLiteralExpression',
{ visitAllChildren: true }
)[0] as ObjectLiteralExpression;
)[0] as ArrayLiteralExpression;
const endOfPropertiesPos = mfRemotesNode.properties.end;
const endOfPropertiesPos = mfRemotesNode.getEnd() - 1;
const isCommaNeeded = checkIsCommaNeeded(mfRemotesNode.getText());
const updatedConfig = `${hostWebpackConfig.slice(0, endOfPropertiesPos)}
\t\t"${options.appName}": 'http://localhost:${
options.port ?? 4200
}/remoteEntry.js',${hostWebpackConfig.slice(endOfPropertiesPos)}`;
const updatedConfig = `${hostWebpackConfig.slice(0, endOfPropertiesPos)}${
isCommaNeeded ? ',' : ''
}'${options.appName}',${hostWebpackConfig.slice(endOfPropertiesPos)}`;
host.write(hostWebpackPath, updatedConfig);

View File

@ -1,21 +1,7 @@
import type { Tree } from '@nrwl/devkit';
import {
generateFiles,
joinPathFragments,
logger,
offsetFromRoot,
} from '@nrwl/devkit';
import { getRelativePathToRootTsConfig } from '@nrwl/workspace/src/utilities/typescript';
import { generateFiles, joinPathFragments, logger } from '@nrwl/devkit';
import type { Schema } from '../schema';
const SHARED_SINGLETON_LIBRARIES = [
'@angular/core',
'@angular/common',
'@angular/common/http',
'@angular/router',
'rxjs',
];
export function generateWebpackConfig(
host: Tree,
options: Schema,
@ -41,10 +27,7 @@ export function generateWebpackConfig(
type: options.mfeType,
name: options.appName,
remotes: remotesWithPorts ?? [],
sourceRoot: appRoot,
sharedLibraries: SHARED_SINGLETON_LIBRARIES,
offsetFromRoot: offsetFromRoot(appRoot),
rootTsConfigPath: getRelativePathToRootTsConfig(host, appRoot),
projectRoot: appRoot,
}
);
}

View File

@ -1,5 +1,5 @@
import type { ProjectConfiguration, Tree } from '@nrwl/devkit';
import { readJson, readProjectConfiguration } from '@nrwl/devkit';
import { readProjectConfiguration } from '@nrwl/devkit';
import { createTreeWithEmptyWorkspace } from '@nrwl/devkit/testing';
import { setupMfe } from './setup-mfe';
@ -43,35 +43,6 @@ describe('Init MFE', () => {
}
);
test.each([
['app1', 'host'],
['remote1', 'remote'],
])(
'should support a root tsconfig.json instead of tsconfig.base.json',
async (app, type: 'host' | 'remote') => {
// ARRANGE
host.rename('tsconfig.base.json', 'tsconfig.json');
// ACT
await setupMfe(host, {
appName: app,
mfeType: type,
});
// ASSERT
expect(host.exists(`apps/${app}/webpack.config.js`)).toBeTruthy();
expect(host.exists(`apps/${app}/webpack.prod.config.js`)).toBeTruthy();
const webpackContents = host.read(
`apps/${app}/webpack.config.js`,
'utf-8'
);
expect(webpackContents).toContain(
"const tsConfigPath = process.env.NX_TSCONFIG_PATH ?? path.join(__dirname, '../../tsconfig.json');"
);
}
);
test.each([
['app1', 'host'],
['remote1', 'remote'],
@ -147,27 +118,6 @@ describe('Init MFE', () => {
}
);
test.each([
['app1', 'host'],
['remote1', 'remote'],
])(
'should install @angular-architects/module-federation in the monorepo',
async (app, type: 'host' | 'remote') => {
// ACT
await setupMfe(host, {
appName: app,
mfeType: type,
});
// ASSERT
const { dependencies } = readJson(host, 'package.json');
expect(
dependencies['@angular-architects/module-federation']
).toBeTruthy();
}
);
it('should add the remote config to the host when --remotes flag supplied', async () => {
// ACT
await setupMfe(host, {
@ -179,9 +129,7 @@ describe('Init MFE', () => {
// ASSERT
const webpackContents = host.read(`apps/app1/webpack.config.js`, 'utf-8');
expect(webpackContents).toContain(
'"remote1": "http://localhost:4200/remoteEntry.js"'
);
expect(webpackContents).toContain(`'remote1'`);
});
it('should update the implicit dependencies of the host when --remotes flag supplied', async () => {
// ACT

View File

@ -1,11 +1,7 @@
import type { GeneratorCallback, Tree } from '@nrwl/devkit';
import type { Tree } from '@nrwl/devkit';
import type { Schema } from './schema';
import {
readProjectConfiguration,
addDependenciesToPackageJson,
formatFiles,
} from '@nrwl/devkit';
import { readProjectConfiguration, formatFiles } from '@nrwl/devkit';
import {
addCypressOnErrorWorkaround,
@ -19,7 +15,6 @@ import {
setupServeTarget,
updateTsConfigTarget,
} from './lib';
import { angularArchitectsModuleFederationPluginVersion } from '../../utils/versions';
export async function setupMfe(host: Tree, options: Schema) {
const projectConfig = readProjectConfiguration(host, options.appName);
@ -39,25 +34,10 @@ export async function setupMfe(host: Tree, options: Schema) {
addCypressOnErrorWorkaround(host, options);
let installPackages: GeneratorCallback = () => {};
if (!options.skipPackageJson) {
// add package to install
installPackages = addDependenciesToPackageJson(
host,
{
'@angular-architects/module-federation':
angularArchitectsModuleFederationPluginVersion,
},
{}
);
}
// format files
if (!options.skipFormat) {
await formatFiles(host);
}
return installPackages;
}
export default setupMfe;

View File

@ -19,7 +19,7 @@ export function getMfeProjects(tree: Tree) {
const ast = tsquery.ast(webpackConfig);
const moduleFederationWebpackConfig = tsquery(
ast,
'Identifier[name=ModuleFederationPlugin]',
'Identifier[name=withModuleFederation]',
{
visitAllChildren: true,
}

View File

@ -6,7 +6,6 @@ export const ngrxVersion = '~13.0.0';
export const rxjsVersion = '~7.4.0';
export const jestPresetAngularVersion = '11.1.1';
export const angularEslintVersion = '~13.1.0';
export const angularArchitectsModuleFederationPluginVersion = '^14.0.1';
export const tailwindVersion = '^3.0.2';
export const postcssVersion = '^8.4.5';
export const autoprefixerVersion = '^10.4.0';