Skip to content

Commit

Permalink
Merge pull request #23978 from mshima/skip_ci-angular-mf2
Browse files Browse the repository at this point in the history
simplify microfrontend config and change vue to lazy load remotes
  • Loading branch information
DanielFran authored Oct 28, 2023
2 parents e86b8eb + 9f8f695 commit 8d1e8d5
Show file tree
Hide file tree
Showing 11 changed files with 123 additions and 219 deletions.
1 change: 1 addition & 0 deletions generators/angular/resources/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
"zone.js": "0.13.3"
},
"devDependencies": {
"@angular-architects/module-federation": "16.0.4",
"@angular-architects/module-federation-runtime": "16.0.4",
"@angular-builders/custom-webpack": "16.0.1",
"@angular-builders/jest": "16.0.1",
Expand Down
7 changes: 4 additions & 3 deletions generators/angular/templates/package.json.ejs
Original file line number Diff line number Diff line change
Expand Up @@ -57,16 +57,17 @@
<%_ if (communicationSpringWebsocket) { _%>
"sockjs-client": "1.6.1",
"@stomp/rx-stomp": "1.2.0",
<%_ } _%>
<%_ if (skipServer) { _%>
"sonar-scanner": "3.1.0",
<%_ } _%>
"tslib": "<%= nodeDependencies['tslib'] %>",
"zone.js": "<%= nodeDependencies['zone.js'] %>"
},
"devDependencies": {
<%_ if (skipServer) { _%>
"sonar-scanner": "3.1.0",
<%_ } _%>
<%_ if (microfrontend && applicationTypeGateway) { _%>
"@angular-architects/module-federation-runtime": "<%= nodeDependencies['@angular-architects/module-federation-runtime'] %>",
"@angular-architects/module-federation": "<%= nodeDependencies['@angular-architects/module-federation'] %>",
<%_ } _%>
<%_ if (communicationSpringWebsocket) { _%>
"@types/sockjs-client": "1.5.1",
Expand Down
174 changes: 48 additions & 126 deletions generators/angular/templates/webpack/webpack.microfrontend.js.ejs
Original file line number Diff line number Diff line change
Expand Up @@ -16,138 +16,60 @@
See the License for the specific language governing permissions and
limitations under the License.
-%>
const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin');
const { withModuleFederationPlugin } = require('@angular-architects/module-federation/webpack');
const packageJson = require('../package.json');
const appVersion = packageJson.version;
// Microfrontend api, should match across gateway and microservices.
const apiVersion = '0.0.1';

const sharedDefaults = { singleton: true, strictVersion: true, requiredVersion: apiVersion };
const shareAllDefaults = { ...sharedDefaults, requiredVersion: 'auto' }
const shareMappings = (...mappings) => Object.fromEntries(mappings.map(map => [map, { ...sharedDefaults, version: apiVersion }]));

const shareDependencies = ({ skipList = [] } = {}) =>
Object.fromEntries(
Object.entries(packageJson.dependencies)
.filter(([dependency]) => !skipList.includes(dependency))
.map(([dependency, version]) => [dependency, { ...sharedDefaults, version, requiredVersion: version }]),
);

let sharedDependencies = shareDependencies({ skipList: ['@angular/localize'] });
sharedDependencies = {
...sharedDependencies,
'@angular/common/http': sharedDependencies['@angular/common'],
'rxjs/operators': sharedDependencies.rxjs,
};

module.exports = (config, options, targetOptions) => {
return {
experiments: {
outputModule: true,
},
plugins: [
new ModuleFederationPlugin({
library: {
type: 'module',
},
return withModuleFederationPlugin({
name: '<%= lowercaseBaseName %>',
<%_ if (applicationTypeMicroservice) { _%>
name: '<%= lowercaseBaseName %>',
filename: 'remoteEntry.js',
exposes: {
exposes: {
<%_ if (enableTranslation) { _%>
'./translation-module': 'app/shared/language/translation.module.ts',
'./translation-module': 'app/shared/language/translation.module.ts',
<%_ } _%>
'./entity-navbar-items': 'app/entities/entity-navbar-items.ts',
'./entity-routing': 'app/entities/entity-routing.module.ts',
},
<%_ } _%>
<%_ if (applicationTypeGateway) { _%>
remotes: {},
<%_ } _%>
shared: {
// { eager?, import?, packageName?, requiredVersion?, shareKey?, shareScope?, singleton?, strictVersion?, version? }
'@angular/core': { singleton: true, strictVersion: true, requiredVersion: '<%= nodeDependencies['@angular/common'] %>' },
'@angular/common': { singleton: true, strictVersion: true, requiredVersion: '<%= nodeDependencies['@angular/common'] %>' },
'@angular/common/http': { singleton: true, strictVersion: true, requiredVersion: '<%= nodeDependencies['@angular/common'] %>' },
'@angular/router': { singleton: true, strictVersion: true, requiredVersion: '<%= nodeDependencies['@angular/common'] %>' },
'@angular/forms': { singleton: true, strictVersion: true, requiredVersion: '<%= nodeDependencies['@angular/common'] %>' },
'@angular/platform-browser': { singleton: true, strictVersion: true, requiredVersion: '<%= nodeDependencies['@angular/common'] %>' },
'@fortawesome/angular-fontawesome': { singleton: true, strictVersion: true, requiredVersion: '<%= nodeDependencies['@fortawesome/angular-fontawesome'] %>' },
'@fortawesome/fontawesome-common-types': { singleton: true, strictVersion: true },
'@fortawesome/fontawesome-svg-core': { singleton: true, strictVersion: true, requiredVersion: '<%= nodeDependencies['@fortawesome/fontawesome-svg-core'] %>' },
'@fortawesome/free-solid-svg-icons': { singleton: true },
'@ng-bootstrap/ng-bootstrap': { singleton: true, strictVersion: true, requiredVersion: '<%= nodeDependencies['@ng-bootstrap/ng-bootstrap'] %>' },
'@ngx-translate/core': { singleton: true, strictVersion: true, requiredVersion: '<%= nodeDependencies['@ngx-translate/core'] %>' },
'@ngx-translate/http-loader': { singleton: true, strictVersion: true, requiredVersion: '<%= nodeDependencies['@ngx-translate/http-loader'] %>' },
dayjs: { singleton: true, strictVersion: true, requiredVersion: '<%= nodeDependencies['dayjs'] %>' },
'ngx-infinite-scroll': { singleton: true, strictVersion: true, requiredVersion: '<%= nodeDependencies['ngx-infinite-scroll'] %>' },
rxjs: { singleton: true, strictVersion: true, requiredVersion: '<%= nodeDependencies['rxjs'] %>' },
'rxjs/operators': { singleton: true, strictVersion: true, requiredVersion: '<%= nodeDependencies['rxjs'] %>' },
'zone.js': { singleton: true, strictVersion: true, requiredVersion: '<%= nodeDependencies['zone.js'] %>' },
'app/config/input.constants': {
singleton: true,
import: 'app/config/input.constants',
requiredVersion: appVersion,
},
'app/config/pagination.constants': {
singleton: true,
import: 'app/config/pagination.constants',
requiredVersion: appVersion,
},
'app/config/translation.config': {
singleton: true,
import: 'app/config/translation.config',
requiredVersion: appVersion,
},
'app/core/auth': {
singleton: true,
import: 'app/core/auth',
requiredVersion: appVersion,
},
'app/core/config': {
singleton: true,
import: 'app/core/config',
requiredVersion: appVersion,
},
'app/core/interceptor': {
singleton: true,
import: 'app/core/interceptor',
requiredVersion: appVersion,
},
'app/core/request': {
singleton: true,
import: 'app/core/request',
requiredVersion: appVersion,
},
'app/core/util': {
singleton: true,
import: 'app/core/util',
requiredVersion: appVersion,
},
'app/shared': {
singleton: true,
import: 'app/shared',
requiredVersion: appVersion,
},
'app/shared/alert': {
singleton: true,
import: 'app/shared/alert',
requiredVersion: appVersion,
},
'app/shared/auth': {
singleton: true,
import: 'app/shared/auth',
requiredVersion: appVersion,
},
'app/shared/date': {
singleton: true,
import: 'app/shared/date',
requiredVersion: appVersion,
},
'app/shared/language': {
singleton: true,
import: 'app/shared/language',
requiredVersion: appVersion,
},
'app/shared/pagination': {
singleton: true,
import: 'app/shared/pagination',
requiredVersion: appVersion,
},
'app/shared/sort': {
singleton: true,
import: 'app/shared/sort',
requiredVersion: appVersion,
},
},
}),
],
output: {
publicPath: 'auto',
uniqueName: '<%= lowercaseBaseName %>',
'./entity-navbar-items': 'app/entities/entity-navbar-items.ts',
'./entity-routing': 'app/entities/entity-routing.module.ts',
},
optimization: {
runtimeChunk: false,
<%_ } _%>
shared: {
...sharedDependencies,
...shareMappings(
'app/config/input.constants',
'app/config/pagination.constants',
'app/config/translation.config',
'app/core/auth',
'app/core/config',
'app/core/interceptor',
'app/core/request',
'app/core/util',
'app/shared',
'app/shared/alert',
'app/shared/auth',
'app/shared/date',
'app/shared/language',
'app/shared/pagination',
'app/shared/sort',
),
},
};
});
};
2 changes: 2 additions & 0 deletions generators/app/__snapshots__/generator.spec.mts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -461,6 +461,7 @@ exports[`generator - app with default config should match snapshot 1`] = `
"rtl": false,
},
"nodeDependencies": {
"@angular-architects/module-federation": "ANGULAR_ARCHITECTS_MODULE_FEDERATION_VERSION",
"@angular-architects/module-federation-runtime": "ANGULAR_ARCHITECTS_MODULE_FEDERATION_RUNTIME_VERSION",
"@angular-builders/custom-webpack": "ANGULAR_BUILDERS_CUSTOM_WEBPACK_VERSION",
"@angular-builders/jest": "ANGULAR_BUILDERS_JEST_VERSION",
Expand Down Expand Up @@ -1029,6 +1030,7 @@ exports[`generator - app with gateway should match snapshot 1`] = `
"rtl": false,
},
"nodeDependencies": {
"@angular-architects/module-federation": "ANGULAR_ARCHITECTS_MODULE_FEDERATION_VERSION",
"@angular-architects/module-federation-runtime": "ANGULAR_ARCHITECTS_MODULE_FEDERATION_RUNTIME_VERSION",
"@angular-builders/custom-webpack": "ANGULAR_BUILDERS_CUSTOM_WEBPACK_VERSION",
"@angular-builders/jest": "ANGULAR_BUILDERS_JEST_VERSION",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
// Register sections and max allowed fragments, 0 for unlimited.
fragments.registerSections({
importsSection:0,
configSection: 0,
moduleFederationSection: 0,
pluginsSection: 0,
});
Expand All @@ -28,7 +29,18 @@ _&>
const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin');
<&- fragments.importsSection() &>
const packageJson = require('../package.json');
const appVersion = packageJson.version;
// Microfrontend api, should match across gateway and microservices.
const apiVersion = '0.0.1';

const sharedDefaults = { singleton: true, strictVersion: true, requiredVersion: apiVersion };
const shareMappings = (...mappings) => Object.fromEntries(mappings.map(map => [map, { ...sharedDefaults, version: apiVersion }]));

const shareDependencies = ({ skipList = [] } = {}) =>
Object.fromEntries(
Object.entries(packageJson.dependencies)
.filter(([dependency]) => !skipList.includes(dependency))
.map(([dependency, version]) => [dependency, { ...sharedDefaults, version, requiredVersion: version }]),
);

module.exports = ({ serve }) => {
return {
Expand All @@ -37,6 +49,7 @@ module.exports = ({ serve }) => {
chunkIds: 'named',
runtimeChunk: false,
},
<&- fragments.configSection() &>
plugins: [
new ModuleFederationPlugin({
<%_ if (applicationTypeMicroservice) { _%>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,57 +29,19 @@ const { DefinePlugin } = require('webpack');
},
<%_ } _%>
shared: {
...Object.fromEntries(Object.entries(packageJson.dependencies).map(([module, version]) => ([module, { requiredVersion: version, singleton: true, shareScope: 'default' }]))),
'app/config/constants': {
singleton: true,
import: 'app/config/constants',
requiredVersion: appVersion,
},
'app/config/store': {
singleton: true,
import: 'app/config/store',
requiredVersion: appVersion,
},
'app/shared/error/error-boundary-routes': {
singleton: true,
import: 'app/shared/error/error-boundary-routes',
requiredVersion: appVersion,
},
'app/shared/layout/menus/menu-components': {
singleton: true,
import: 'app/shared/layout/menus/menu-components',
requiredVersion: appVersion,
},
'app/shared/layout/menus/menu-item': {
singleton: true,
import: 'app/shared/layout/menus/menu-item',
requiredVersion: appVersion,
},
'app/shared/reducers': {
singleton: true,
import: 'app/shared/reducers',
requiredVersion: appVersion,
},
'app/shared/reducers/locale': {
singleton: true,
import: 'app/shared/reducers/locale',
requiredVersion: appVersion,
},
'app/shared/reducers/reducer.utils': {
singleton: true,
import: 'app/shared/reducers/reducer.utils',
requiredVersion: appVersion,
},
'app/shared/util/date-utils': {
singleton: true,
import: 'app/shared/util/date-utils',
requiredVersion: appVersion,
},
'app/shared/util/entity-utils': {
singleton: true,
import: 'app/shared/util/entity-utils',
requiredVersion: appVersion,
},
...shareDependencies(),
...shareMappings(
'app/config/constants',
'app/config/store',
'app/shared/error/error-boundary-routes',
'app/shared/layout/menus/menu-components',
'app/shared/layout/menus/menu-item',
'app/shared/reducers',
'app/shared/reducers/locale',
'app/shared/reducers/reducer.utils',
'app/shared/util/date-utils',
'app/shared/util/entity-utils',
),
},
<&_ } -&>
<&_ if (fragment.pluginsSection) { -&>
Expand Down
1 change: 1 addition & 0 deletions generators/vue/resources/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
"vue-router": "4.2.5"
},
"devDependencies": {
"@module-federation/utilities": "3.0.3-0",
"@pinia/testing": "0.1.3",
"@rushstack/eslint-patch": "1.5.1",
"@tsconfig/node18": "18.2.2",
Expand Down
3 changes: 3 additions & 0 deletions generators/vue/templates/package.json.ejs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@
"vue-router": "<%= nodeDependencies['vue-router'] %>"
},
"devDependencies": {
<%_ if (applicationTypeGateway && microfrontend) { _%>
"@module-federation/utilities": "<%= nodeDependencies['@module-federation/utilities'] %>",
<%_ } _%>
<%_ if (microfrontend) { _%>
"@originjs/vite-plugin-federation": "1.2.3",
"browser-sync-webpack-plugin": "<%= nodeDependencies['browser-sync-webpack-plugin'] %>",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,23 @@ import EntitiesMenu from '@/entities/entities-menu.vue';

import { useStore } from '@/store';
import { useRouter } from 'vue-router';
<%_ if (applicationTypeGateway && microfrontend) { _%>
import { importRemote } from '@module-federation/utilities';
<%_ } _%>

export default defineComponent({
compatConfig: { MODE: 3 },
name: 'JhiNavbar',
components: {
'entities-menu': EntitiesMenu,
<%_ if (applicationTypeGateway && microfrontend) { _%>
<%_ for (const microfrontend of microfrontends) { _%>
'<%= microfrontend.lowercaseBaseName %>-menu': defineAsyncComponent(() => {
return import('@<%= microfrontend.lowercaseBaseName %>/entities-menu').catch(() => import('@/core/error/error-loading.vue'));
<%_ for (const remote of microfrontends) { _%>
'<%= remote.lowercaseBaseName %>-menu': defineAsyncComponent(() => {
return importRemote<any>({
url: `./<%= remote.endpointPrefix %>`,
scope: '<%= remote.lowercaseBaseName %>',
module: './entities-menu',
}).catch(() => import('@/core/error/error-loading.vue'));
}),
<%_ } _%>
<%_ } _%>
Expand Down
Loading

0 comments on commit 8d1e8d5

Please sign in to comment.