├── .editorconfig
├── .gitignore
├── README.md
├── angular.json
├── index.html
├── package-lock.json
├── package.json
├── projects
├── mfe1
│ ├── browserslist
│ ├── e2e
│ │ ├── protractor.conf.js
│ │ ├── src
│ │ │ ├── app.e2e-spec.ts
│ │ │ └── app.po.ts
│ │ └── tsconfig.json
│ ├── karma.conf.js
│ ├── src
│ │ ├── app
│ │ │ ├── app.component.html
│ │ │ ├── app.component.ts
│ │ │ ├── download.component.ts
│ │ │ └── upload.component.ts
│ │ ├── assets
│ │ │ ├── angular.png
│ │ │ ├── download.png
│ │ │ └── upload.png
│ │ ├── bootstrap.ts
│ │ ├── environments
│ │ │ ├── environment.prod.ts
│ │ │ └── environment.ts
│ │ ├── favicon.ico
│ │ ├── index.html
│ │ ├── main.ts
│ │ ├── polyfills.ts
│ │ ├── styles.css
│ │ └── test.ts
│ ├── tsconfig.app.json
│ ├── tsconfig.spec.json
│ ├── tslint.json
│ ├── webpack.config.js
│ └── webpack.prod.config.js
├── mfe2
│ ├── browserslist
│ ├── e2e
│ │ ├── protractor.conf.js
│ │ ├── src
│ │ │ ├── app.e2e-spec.ts
│ │ │ └── app.po.ts
│ │ └── tsconfig.json
│ ├── karma.conf.js
│ ├── src
│ │ ├── app
│ │ │ ├── ai-analyze.component.ts
│ │ │ ├── analyze.component.ts
│ │ │ ├── app.component.css
│ │ │ ├── app.component.html
│ │ │ ├── app.component.spec.ts
│ │ │ ├── app.component.ts
│ │ │ └── enrich.component.ts
│ │ ├── assets
│ │ │ ├── .gitkeep
│ │ │ ├── analyze.png
│ │ │ ├── android.png
│ │ │ ├── android.webp
│ │ │ ├── angular.png
│ │ │ └── enrich.png
│ │ ├── bootstrap.ts
│ │ ├── environments
│ │ │ ├── environment.prod.ts
│ │ │ └── environment.ts
│ │ ├── favicon.ico
│ │ ├── index.html
│ │ ├── main.ts
│ │ ├── polyfills.ts
│ │ ├── styles.css
│ │ └── test.ts
│ ├── tsconfig.app.json
│ ├── tsconfig.spec.json
│ ├── tslint.json
│ ├── webpack.config.js
│ └── webpack.prod.config.js
└── shell
│ ├── browserslist
│ ├── e2e
│ ├── protractor.conf.js
│ ├── src
│ │ ├── app.e2e-spec.ts
│ │ └── app.po.ts
│ └── tsconfig.json
│ ├── karma.conf.js
│ ├── src
│ ├── app
│ │ ├── app.component.css
│ │ ├── app.component.html
│ │ ├── app.component.ts
│ │ ├── config
│ │ │ ├── config.component.html
│ │ │ ├── config.component.spec.ts
│ │ │ └── config.component.ts
│ │ ├── home
│ │ │ ├── home.component.css
│ │ │ ├── home.component.html
│ │ │ ├── home.component.spec.ts
│ │ │ └── home.component.ts
│ │ └── plugins
│ │ │ ├── lookup.service.ts
│ │ │ ├── plugin-proxy.component.ts
│ │ │ └── plugin.ts
│ ├── assets
│ │ └── angular.png
│ ├── bootstrap.ts
│ ├── environments
│ │ ├── environment.prod.ts
│ │ └── environment.ts
│ ├── favicon.ico
│ ├── index.html
│ ├── main.ts
│ ├── polyfills.ts
│ ├── styles.css
│ └── test.ts
│ ├── tsconfig.app.json
│ ├── tsconfig.spec.json
│ ├── tslint.json
│ ├── webpack.config.js
│ ├── webpack.config.old.js
│ ├── webpack.prod.config.js
│ └── webpack.prod.config.old.js
├── result.png
├── tsconfig.json
└── tslint.json
/.editorconfig:
--------------------------------------------------------------------------------
1 | # Editor configuration, see https://editorconfig.org
2 | root = true
3 |
4 | [*]
5 | charset = utf-8
6 | indent_style = space
7 | indent_size = 2
8 | insert_final_newline = true
9 | trim_trailing_whitespace = true
10 |
11 | [*.ts]
12 | quote_type = single
13 |
14 | [*.md]
15 | max_line_length = off
16 | trim_trailing_whitespace = false
17 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See http://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # compiled output
4 | /dist
5 | /tmp
6 | /out-tsc
7 |
8 | # dependencies
9 | /node_modules
10 |
11 | # IDEs and editors
12 | /.idea
13 | .project
14 | .classpath
15 | .c9/
16 | *.launch
17 | .settings/
18 | *.sublime-workspace
19 |
20 | # IDE - VSCode
21 | .vscode/*
22 | !.vscode/settings.json
23 | !.vscode/tasks.json
24 | !.vscode/launch.json
25 | !.vscode/extensions.json
26 |
27 | # misc
28 | /.angular/cache
29 | /.sass-cache
30 | /connect.lock
31 | /coverage
32 | /libpeerconnection.log
33 | npm-debug.log
34 | yarn-error.log
35 | testem.log
36 | /typings
37 |
38 | # System Files
39 | .DS_Store
40 | Thumbs.db
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # FederationDemo
2 |
3 | Demonstrates webpack 5 Module Federation with Angular and the Angular Router.
4 |
5 | 
6 |
7 | ## Start
8 |
9 | - ``npm run build``
10 | - ``npm run serve:dist``
11 | - Navigate to shell at http://localhost:5000
12 | - Navigate to standalone microfrontend at http://localhost:3000
13 |
14 | ## Disclaimer
15 |
16 | Module Federation is a brand-new technology that will come with webpack 5. As webpack 5 is currently in beta, it's not intended for production yet. Also, to make it work with Angular already today, my examples use a patched version of the Angular CLI and a custom webpack configuration. Once webpack 5 is final and the Angular CLI supports it, we won't need these workarounds anymore but have a more streamlined way for all of this. Nevertheless, investigating this technology already today gives us a sound idea of what's possible shortly.
17 |
18 | For the same reason, this example does not support debug mode. Just build and serve it as mentioned above.
--------------------------------------------------------------------------------
/angular.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
3 | "version": 1,
4 | "newProjectRoot": "projects",
5 | "projects": {
6 | "shell": {
7 | "projectType": "application",
8 | "schematics": {},
9 | "root": "projects/shell",
10 | "sourceRoot": "projects/shell/src",
11 | "prefix": "app",
12 | "architect": {
13 | "build": {
14 | "builder": "ngx-build-plus:browser",
15 | "options": {
16 | "outputPath": "dist/shell",
17 | "index": "projects/shell/src/index.html",
18 | "main": "projects/shell/src/main.ts",
19 | "polyfills": "projects/shell/src/polyfills.ts",
20 | "tsConfig": "projects/shell/tsconfig.app.json",
21 | "aot": true,
22 | "assets": [
23 | "projects/shell/src/favicon.ico",
24 | "projects/shell/src/assets"
25 | ],
26 | "styles": [
27 | "projects/shell/src/styles.css"
28 | ],
29 | "scripts": [],
30 | "extraWebpackConfig": "projects/shell/webpack.config.js",
31 | "commonChunk": false
32 | },
33 | "configurations": {
34 | "development": {
35 | "optimization": false,
36 | "sourceMap": true,
37 | "buildOptimizer": false
38 | },
39 | "production": {
40 | "fileReplacements": [
41 | {
42 | "replace": "projects/shell/src/environments/environment.ts",
43 | "with": "projects/shell/src/environments/environment.prod.ts"
44 | }
45 | ],
46 | "optimization": true,
47 | "outputHashing": "all",
48 | "sourceMap": false,
49 | "extractCss": true,
50 | "namedChunks": false,
51 | "extractLicenses": true,
52 | "vendorChunk": false,
53 | "buildOptimizer": true,
54 | "extraWebpackConfig": "projects/shell/webpack.prod.config.js"
55 | }
56 | }
57 | },
58 | "serve": {
59 | "builder": "ngx-build-plus:dev-server",
60 | "options": {
61 | "browserTarget": "shell:build",
62 | "publicHost": "http://localhost:4200",
63 | "port": 4200,
64 | "extraWebpackConfig": "projects/shell/webpack.config.js"
65 | },
66 | "configurations": {
67 | "development": {
68 | "browserTarget": "shell:build:development",
69 | "extraWebpackConfig": "projects/shell/webpack.prod.config.js"
70 | },
71 | "production": {
72 | "browserTarget": "shell:build:production",
73 | "extraWebpackConfig": "projects/shell/webpack.prod.config.js"
74 | }
75 | },
76 | "defaultConfiguration": "development"
77 | },
78 | "extract-i18n": {
79 | "builder": "ngx-build-plus:extract-i18n",
80 | "options": {
81 | "browserTarget": "shell:build",
82 | "extraWebpackConfig": "projects/shell/webpack.config.js"
83 | }
84 | },
85 | "test": {
86 | "builder": "ngx-build-plus:karma",
87 | "options": {
88 | "main": "projects/shell/src/test.ts",
89 | "polyfills": "projects/shell/src/polyfills.ts",
90 | "tsConfig": "projects/shell/tsconfig.spec.json",
91 | "karmaConfig": "projects/shell/karma.conf.js",
92 | "assets": [
93 | "projects/shell/src/favicon.ico",
94 | "projects/shell/src/assets"
95 | ],
96 | "styles": [
97 | "projects/shell/src/styles.css"
98 | ],
99 | "scripts": [],
100 | "extraWebpackConfig": "projects/shell/webpack.config.js"
101 | }
102 | },
103 | "e2e": {
104 | "builder": "@angular-devkit/build-angular:protractor",
105 | "options": {
106 | "protractorConfig": "projects/shell/e2e/protractor.conf.js",
107 | "devServerTarget": "shell:serve"
108 | },
109 | "configurations": {
110 | "production": {
111 | "devServerTarget": "shell:serve:production"
112 | }
113 | }
114 | }
115 | }
116 | },
117 | "mfe1": {
118 | "projectType": "application",
119 | "schematics": {},
120 | "root": "projects/mfe1",
121 | "sourceRoot": "projects/mfe1/src",
122 | "prefix": "app",
123 | "architect": {
124 | "build": {
125 | "builder": "ngx-build-plus:browser",
126 | "options": {
127 | "outputPath": "dist/mfe1",
128 | "index": "projects/mfe1/src/index.html",
129 | "main": "projects/mfe1/src/main.ts",
130 | "polyfills": "projects/mfe1/src/polyfills.ts",
131 | "tsConfig": "projects/mfe1/tsconfig.app.json",
132 | "aot": true,
133 | "assets": [
134 | "projects/mfe1/src/favicon.ico",
135 | "projects/mfe1/src/assets"
136 | ],
137 | "styles": [
138 | "projects/mfe1/src/styles.css"
139 | ],
140 | "scripts": [],
141 | "extraWebpackConfig": "projects/mfe1/webpack.config.js",
142 | "commonChunk": false
143 | },
144 | "configurations": {
145 | "development": {
146 | "optimization": false,
147 | "sourceMap": true,
148 | "buildOptimizer": false
149 | },
150 | "production": {
151 | "fileReplacements": [
152 | {
153 | "replace": "projects/mfe1/src/environments/environment.ts",
154 | "with": "projects/mfe1/src/environments/environment.prod.ts"
155 | }
156 | ],
157 | "optimization": true,
158 | "outputHashing": "all",
159 | "sourceMap": false,
160 | "extractCss": true,
161 | "namedChunks": false,
162 | "extractLicenses": true,
163 | "vendorChunk": false,
164 | "buildOptimizer": true,
165 | "extraWebpackConfig": "projects/mfe1/webpack.prod.config.js"
166 | }
167 | }
168 | },
169 | "serve": {
170 | "builder": "ngx-build-plus:dev-server",
171 | "options": {
172 | "browserTarget": "mfe1:build",
173 | "publicHost": "http://localhost:4201",
174 | "port": 4201,
175 | "extraWebpackConfig": "projects/mfe1/webpack.config.js"
176 | },
177 | "configurations": {
178 | "development": {
179 | "browserTarget": "mfe1:build:development",
180 | "extraWebpackConfig": "projects/mfe1/webpack.prod.config.js"
181 | },
182 | "production": {
183 | "browserTarget": "mfe1:build:production",
184 | "extraWebpackConfig": "projects/mfe1/webpack.prod.config.js"
185 | }
186 | },
187 | "defaultConfiguration": "development"
188 | },
189 | "extract-i18n": {
190 | "builder": "ngx-build-plus:extract-i18n",
191 | "options": {
192 | "browserTarget": "mfe1:build",
193 | "extraWebpackConfig": "projects/mfe1/webpack.config.js"
194 | }
195 | },
196 | "test": {
197 | "builder": "ngx-build-plus:karma",
198 | "options": {
199 | "main": "projects/mfe1/src/test.ts",
200 | "polyfills": "projects/mfe1/src/polyfills.ts",
201 | "tsConfig": "projects/mfe1/tsconfig.spec.json",
202 | "karmaConfig": "projects/mfe1/karma.conf.js",
203 | "assets": [
204 | "projects/mfe1/src/favicon.ico",
205 | "projects/mfe1/src/assets"
206 | ],
207 | "styles": [
208 | "projects/mfe1/src/styles.css"
209 | ],
210 | "scripts": [],
211 | "extraWebpackConfig": "projects/mfe1/webpack.config.js"
212 | }
213 | },
214 | "e2e": {
215 | "builder": "@angular-devkit/build-angular:protractor",
216 | "options": {
217 | "protractorConfig": "projects/mfe1/e2e/protractor.conf.js",
218 | "devServerTarget": "mfe1:serve"
219 | },
220 | "configurations": {
221 | "production": {
222 | "devServerTarget": "mfe1:serve:production"
223 | }
224 | }
225 | }
226 | }
227 | },
228 | "mfe2": {
229 | "projectType": "application",
230 | "schematics": {},
231 | "root": "projects/mfe2",
232 | "sourceRoot": "projects/mfe2/src",
233 | "prefix": "app",
234 | "architect": {
235 | "build": {
236 | "builder": "ngx-build-plus:browser",
237 | "options": {
238 | "outputPath": "dist/mfe2",
239 | "index": "projects/mfe2/src/index.html",
240 | "main": "projects/mfe2/src/main.ts",
241 | "polyfills": "projects/mfe2/src/polyfills.ts",
242 | "tsConfig": "projects/mfe2/tsconfig.app.json",
243 | "aot": true,
244 | "assets": [
245 | "projects/mfe2/src/favicon.ico",
246 | "projects/mfe2/src/assets"
247 | ],
248 | "styles": [
249 | "projects/mfe2/src/styles.css"
250 | ],
251 | "scripts": [],
252 | "extraWebpackConfig": "projects/mfe2/webpack.config.js",
253 | "commonChunk": false
254 | },
255 | "configurations": {
256 | "development": {
257 | "optimization": false,
258 | "sourceMap": true,
259 | "buildOptimizer": false
260 | },
261 | "production": {
262 | "fileReplacements": [
263 | {
264 | "replace": "projects/mfe2/src/environments/environment.ts",
265 | "with": "projects/mfe2/src/environments/environment.prod.ts"
266 | }
267 | ],
268 | "optimization": true,
269 | "outputHashing": "all",
270 | "sourceMap": false,
271 | "extractCss": true,
272 | "namedChunks": false,
273 | "extractLicenses": true,
274 | "vendorChunk": false,
275 | "buildOptimizer": true,
276 | "budgets": [
277 | {
278 | "type": "initial",
279 | "maximumWarning": "2mb",
280 | "maximumError": "5mb"
281 | },
282 | {
283 | "type": "anyComponentStyle",
284 | "maximumWarning": "6kb",
285 | "maximumError": "10kb"
286 | }
287 | ],
288 | "extraWebpackConfig": "projects/mfe2/webpack.prod.config.js"
289 | }
290 | }
291 | },
292 | "serve": {
293 | "builder": "ngx-build-plus:dev-server",
294 | "options": {
295 | "browserTarget": "mfe2:build",
296 | "extraWebpackConfig": "projects/mfe2/webpack.config.js",
297 | "publicHost": "http://localhost:4202",
298 | "port": 4202
299 | },
300 | "configurations": {
301 | "development": {
302 | "browserTarget": "mfe2:build:development",
303 | "extraWebpackConfig": "projects/mfe2/webpack.prod.config.js"
304 | },
305 | "production": {
306 | "browserTarget": "mfe2:build:production",
307 | "extraWebpackConfig": "projects/mfe2/webpack.prod.config.js"
308 | }
309 | },
310 | "defaultConfiguration": "development"
311 | },
312 | "extract-i18n": {
313 | "builder": "ngx-build-plus:extract-i18n",
314 | "options": {
315 | "browserTarget": "mfe2:build",
316 | "extraWebpackConfig": "projects/mfe2/webpack.config.js"
317 | }
318 | },
319 | "test": {
320 | "builder": "ngx-build-plus:karma",
321 | "options": {
322 | "main": "projects/mfe2/src/test.ts",
323 | "polyfills": "projects/mfe2/src/polyfills.ts",
324 | "tsConfig": "projects/mfe2/tsconfig.spec.json",
325 | "karmaConfig": "projects/mfe2/karma.conf.js",
326 | "assets": [
327 | "projects/mfe2/src/favicon.ico",
328 | "projects/mfe2/src/assets"
329 | ],
330 | "styles": [
331 | "projects/mfe2/src/styles.css"
332 | ],
333 | "scripts": [],
334 | "extraWebpackConfig": "projects/mfe2/webpack.config.js"
335 | }
336 | },
337 | "e2e": {
338 | "builder": "@angular-devkit/build-angular:protractor",
339 | "options": {
340 | "protractorConfig": "projects/mfe2/e2e/protractor.conf.js",
341 | "devServerTarget": "mfe2:serve"
342 | },
343 | "configurations": {
344 | "production": {
345 | "devServerTarget": "mfe2:serve:production"
346 | }
347 | }
348 | }
349 | }
350 | }
351 | }
352 | }
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | Demo
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "mf-demo",
3 | "version": "0.0.0",
4 | "scripts": {
5 | "ng": "ng",
6 | "start:shell": "ng serve shell -o",
7 | "start:mfe1": "ng serve mfe1 -o",
8 | "start:mfe2": "ng serve mfe2 -o",
9 | "build:shell": "ng build shell --prod",
10 | "build:mfe1": "ng build mfe1 --prod",
11 | "build:mfe2": "ng build mfe2 --prod",
12 | "start": "concurrently \"npm run start:shell\" \"npm run start:mfe1\" \"npm run start:mfe2\" ",
13 | "build": "npm run build:shell && npm run build:mfe1 && npm run build:mfe2",
14 | "test": "ng test",
15 | "lint": "ng lint",
16 | "e2e": "ng e2e",
17 | "run:all": "node node_modules/@angular-architects/module-federation/src/server/mf-dev-server.js"
18 | },
19 | "private": true,
20 | "dependencies": {
21 | "@angular-architects/module-federation": "^14.3.8",
22 | "@angular/animations": "^14.0.1",
23 | "@angular/common": "^14.0.1",
24 | "@angular/compiler": "^14.0.1",
25 | "@angular/core": "^14.0.1",
26 | "@angular/forms": "^14.0.1",
27 | "@angular/platform-browser": "^14.0.1",
28 | "@angular/platform-browser-dynamic": "^14.0.1",
29 | "@angular/router": "^14.0.1",
30 | "@nrwl/workspace": "^10.3.0",
31 | "concurrently": "^5.3.0",
32 | "rxjs": "~6.6.0",
33 | "tslib": "^2.0.0",
34 | "webpack": "^5.65.0",
35 | "webpack-dev-server": "^4.7.1",
36 | "zone.js": "~0.11.4"
37 | },
38 | "devDependencies": {
39 | "@angular-devkit/build-angular": "^14.0.1",
40 | "@angular/cli": "^14.0.1",
41 | "@angular/compiler-cli": "^14.0.1",
42 | "@types/jasmine": "~3.5.0",
43 | "@types/jasminewd2": "~2.0.3",
44 | "@types/node": "^12.11.1",
45 | "codelyzer": "^6.0.0",
46 | "jasmine-core": "~3.6.0",
47 | "jasmine-spec-reporter": "~5.0.0",
48 | "karma": "~6.3.9",
49 | "karma-chrome-launcher": "~3.1.0",
50 | "karma-coverage": "~2.0.3",
51 | "karma-jasmine": "~4.0.0",
52 | "karma-jasmine-html-reporter": "^1.5.0",
53 | "ngx-build-plus": "^14.0.0",
54 | "protractor": "~7.0.0",
55 | "serve": "^11.3.2",
56 | "ts-node": "~8.3.0",
57 | "tslint": "~6.1.0",
58 | "typescript": "~4.7.3"
59 | }
60 | }
--------------------------------------------------------------------------------
/projects/mfe1/browserslist:
--------------------------------------------------------------------------------
1 | # This file is used by the build system to adjust CSS and JS output to support the specified browsers below.
2 | # For additional information regarding the format and rule options, please see:
3 | # https://github.com/browserslist/browserslist#queries
4 |
5 | # You can see what browsers were selected by your queries by running:
6 | # npx browserslist
7 |
8 | > 0.5%
9 | last 2 versions
10 | Firefox ESR
11 | not dead
12 | not IE 9-11 # For IE 9-11 support, remove 'not'.
--------------------------------------------------------------------------------
/projects/mfe1/e2e/protractor.conf.js:
--------------------------------------------------------------------------------
1 | // @ts-check
2 | // Protractor configuration file, see link for more information
3 | // https://github.com/angular/protractor/blob/master/lib/config.ts
4 |
5 | const { SpecReporter } = require('jasmine-spec-reporter');
6 |
7 | /**
8 | * @type { import("protractor").Config }
9 | */
10 | exports.config = {
11 | allScriptsTimeout: 11000,
12 | specs: [
13 | './src/**/*.e2e-spec.ts'
14 | ],
15 | capabilities: {
16 | browserName: 'chrome'
17 | },
18 | directConnect: true,
19 | baseUrl: 'http://localhost:4200/',
20 | framework: 'jasmine',
21 | jasmineNodeOpts: {
22 | showColors: true,
23 | defaultTimeoutInterval: 30000,
24 | print: function() {}
25 | },
26 | onPrepare() {
27 | require('ts-node').register({
28 | project: require('path').join(__dirname, './tsconfig.json')
29 | });
30 | jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } }));
31 | }
32 | };
--------------------------------------------------------------------------------
/projects/mfe1/e2e/src/app.e2e-spec.ts:
--------------------------------------------------------------------------------
1 | import { AppPage } from './app.po';
2 | import { browser, logging } from 'protractor';
3 |
4 | describe('workspace-project App', () => {
5 | let page: AppPage;
6 |
7 | beforeEach(() => {
8 | page = new AppPage();
9 | });
10 |
11 | it('should display welcome message', () => {
12 | page.navigateTo();
13 | expect(page.getTitleText()).toEqual('mfe1 app is running!');
14 | });
15 |
16 | afterEach(async () => {
17 | // Assert that there are no errors emitted from the browser
18 | const logs = await browser.manage().logs().get(logging.Type.BROWSER);
19 | expect(logs).not.toContain(jasmine.objectContaining({
20 | level: logging.Level.SEVERE,
21 | } as logging.Entry));
22 | });
23 | });
24 |
--------------------------------------------------------------------------------
/projects/mfe1/e2e/src/app.po.ts:
--------------------------------------------------------------------------------
1 | import { browser, by, element } from 'protractor';
2 |
3 | export class AppPage {
4 | navigateTo(): Promise {
5 | return browser.get(browser.baseUrl) as Promise;
6 | }
7 |
8 | getTitleText(): Promise {
9 | return element(by.css('app-root .content span')).getText() as Promise;
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/projects/mfe1/e2e/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../../tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "../../../out-tsc/e2e",
5 | "module": "commonjs",
6 | "target": "es5",
7 | "types": [
8 | "jasmine",
9 | "jasminewd2",
10 | "node"
11 | ]
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/projects/mfe1/karma.conf.js:
--------------------------------------------------------------------------------
1 | // Karma configuration file, see link for more information
2 | // https://karma-runner.github.io/1.0/config/configuration-file.html
3 |
4 | module.exports = function (config) {
5 | config.set({
6 | basePath: '',
7 | frameworks: ['jasmine', '@angular-devkit/build-angular'],
8 | plugins: [
9 | require('karma-jasmine'),
10 | require('karma-chrome-launcher'),
11 | require('karma-jasmine-html-reporter'),
12 | require('karma-coverage-istanbul-reporter'),
13 | require('@angular-devkit/build-angular/plugins/karma')
14 | ],
15 | client: {
16 | clearContext: false // leave Jasmine Spec Runner output visible in browser
17 | },
18 | coverageIstanbulReporter: {
19 | dir: require('path').join(__dirname, '../../coverage/mfe1'),
20 | reports: ['html', 'lcovonly', 'text-summary'],
21 | fixWebpackSourcePaths: true
22 | },
23 | reporters: ['progress', 'kjhtml'],
24 | port: 9876,
25 | colors: true,
26 | logLevel: config.LOG_INFO,
27 | autoWatch: true,
28 | browsers: ['Chrome'],
29 | singleRun: false,
30 | restartOnFileChange: true
31 | });
32 | };
33 |
--------------------------------------------------------------------------------
/projects/mfe1/src/app/app.component.html:
--------------------------------------------------------------------------------
1 | mfe1
2 |
3 |
4 |
--------------------------------------------------------------------------------
/projects/mfe1/src/app/app.component.ts:
--------------------------------------------------------------------------------
1 | import { Component } from '@angular/core';
2 | import { DownloadComponent } from './download.component';
3 | import { UploadComponent } from './upload.component';
4 |
5 | @Component({
6 | standalone: true,
7 | imports: [
8 | DownloadComponent,
9 | UploadComponent,
10 | ],
11 | selector: 'app-root',
12 | templateUrl: 'app.component.html'
13 | })
14 | export class AppComponent {
15 | }
16 |
--------------------------------------------------------------------------------
/projects/mfe1/src/app/download.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit } from '@angular/core';
2 |
3 | @Component({
4 | standalone: true,
5 | selector: 'mfe1-download',
6 | template: `
7 |
8 |

9 |
Download
10 |
11 | `
12 | })
13 |
14 | export class DownloadComponent implements OnInit {
15 | constructor() { }
16 |
17 | ngOnInit() { }
18 | }
--------------------------------------------------------------------------------
/projects/mfe1/src/app/upload.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit } from '@angular/core';
2 |
3 | @Component({
4 | standalone: true,
5 | selector: 'mfe1-upload',
6 | template: `
7 |
8 |

9 |
Upload
10 |
11 | `
12 | })
13 |
14 | export class UploadComponent implements OnInit {
15 | constructor() { }
16 |
17 | ngOnInit() { }
18 | }
--------------------------------------------------------------------------------
/projects/mfe1/src/assets/angular.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/manfredsteyer/module-federation-with-angular-dynamic-workflow-designer/02243b01c96e52e5257d9cf9dbbfd2beea858691/projects/mfe1/src/assets/angular.png
--------------------------------------------------------------------------------
/projects/mfe1/src/assets/download.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/manfredsteyer/module-federation-with-angular-dynamic-workflow-designer/02243b01c96e52e5257d9cf9dbbfd2beea858691/projects/mfe1/src/assets/download.png
--------------------------------------------------------------------------------
/projects/mfe1/src/assets/upload.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/manfredsteyer/module-federation-with-angular-dynamic-workflow-designer/02243b01c96e52e5257d9cf9dbbfd2beea858691/projects/mfe1/src/assets/upload.png
--------------------------------------------------------------------------------
/projects/mfe1/src/bootstrap.ts:
--------------------------------------------------------------------------------
1 | import { environment } from './environments/environment';
2 | import { enableProdMode } from '@angular/core';
3 | import { bootstrapApplication } from '@angular/platform-browser';
4 | import { AppComponent } from './app/app.component';
5 |
6 | if (environment.production) {
7 | enableProdMode();
8 | }
9 |
10 | bootstrapApplication(AppComponent, {
11 | providers: []
12 | });
--------------------------------------------------------------------------------
/projects/mfe1/src/environments/environment.prod.ts:
--------------------------------------------------------------------------------
1 | export const environment = {
2 | production: true
3 | };
4 |
--------------------------------------------------------------------------------
/projects/mfe1/src/environments/environment.ts:
--------------------------------------------------------------------------------
1 | // This file can be replaced during build by using the `fileReplacements` array.
2 | // `ng build --prod` replaces `environment.ts` with `environment.prod.ts`.
3 | // The list of file replacements can be found in `angular.json`.
4 |
5 | export const environment = {
6 | production: false
7 | };
8 |
9 | /*
10 | * For easier debugging in development mode, you can import the following file
11 | * to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`.
12 | *
13 | * This import should be commented out in production mode because it will have a negative impact
14 | * on performance if an error is thrown.
15 | */
16 | // import 'zone.js/dist/zone-error'; // Included with Angular CLI.
17 |
--------------------------------------------------------------------------------
/projects/mfe1/src/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/manfredsteyer/module-federation-with-angular-dynamic-workflow-designer/02243b01c96e52e5257d9cf9dbbfd2beea858691/projects/mfe1/src/favicon.ico
--------------------------------------------------------------------------------
/projects/mfe1/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Mfe1
6 |
7 |
8 |
9 |
10 |
11 |
12 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/projects/mfe1/src/main.ts:
--------------------------------------------------------------------------------
1 | import('./bootstrap')
2 | .catch(err => console.error(err));
3 |
--------------------------------------------------------------------------------
/projects/mfe1/src/polyfills.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * This file includes polyfills needed by Angular and is loaded before the app.
3 | * You can add your own extra polyfills to this file.
4 | *
5 | * This file is divided into 2 sections:
6 | * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers.
7 | * 2. Application imports. Files imported after ZoneJS that should be loaded before your main
8 | * file.
9 | *
10 | * The current setup is for so-called "evergreen" browsers; the last versions of browsers that
11 | * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera),
12 | * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile.
13 | *
14 | * Learn more in https://angular.io/guide/browser-support
15 | */
16 |
17 | /***************************************************************************************************
18 | * BROWSER POLYFILLS
19 | */
20 |
21 | /**
22 | * By default, zone.js will patch all possible macroTask and DomEvents
23 | * user can disable parts of macroTask/DomEvents patch by setting following flags
24 | * because those flags need to be set before `zone.js` being loaded, and webpack
25 | * will put import in the top of bundle, so user need to create a separate file
26 | * in this directory (for example: zone-flags.ts), and put the following flags
27 | * into that file, and then add the following code before importing zone.js.
28 | * import './zone-flags';
29 | *
30 | * The flags allowed in zone-flags.ts are listed here.
31 | *
32 | * The following flags will work for all browsers.
33 | *
34 | * (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame
35 | * (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick
36 | * (window as any).__zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames
37 | *
38 | * in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js
39 | * with the following flag, it will bypass `zone.js` patch for IE/Edge
40 | *
41 | * (window as any).__Zone_enable_cross_context_check = true;
42 | *
43 | */
44 |
45 | /***************************************************************************************************
46 | * Zone JS is required by default for Angular itself.
47 | */
48 | import 'zone.js/dist/zone'; // Included with Angular CLI.
49 |
50 |
51 | /***************************************************************************************************
52 | * APPLICATION IMPORTS
53 | */
54 |
--------------------------------------------------------------------------------
/projects/mfe1/src/styles.css:
--------------------------------------------------------------------------------
1 | /* You can add global styles to this file, and also import other style files */
2 |
--------------------------------------------------------------------------------
/projects/mfe1/src/test.ts:
--------------------------------------------------------------------------------
1 | // This file is required by karma.conf.js and loads recursively all the .spec and framework files
2 |
3 | import 'zone.js/dist/zone-testing';
4 | import { getTestBed } from '@angular/core/testing';
5 | import {
6 | BrowserDynamicTestingModule,
7 | platformBrowserDynamicTesting
8 | } from '@angular/platform-browser-dynamic/testing';
9 |
10 | declare const require: {
11 | context(path: string, deep?: boolean, filter?: RegExp): {
12 | keys(): string[];
13 | (id: string): T;
14 | };
15 | };
16 |
17 | // First, initialize the Angular testing environment.
18 | getTestBed().initTestEnvironment(
19 | BrowserDynamicTestingModule,
20 | platformBrowserDynamicTesting(), {
21 | teardown: { destroyAfterEach: false }
22 | }
23 | );
24 | // Then we find all the tests.
25 | const context = require.context('./', true, /\.spec\.ts$/);
26 | // And load the modules.
27 | context.keys().map(context);
28 |
--------------------------------------------------------------------------------
/projects/mfe1/tsconfig.app.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "../../out-tsc/app",
5 | "types": [],
6 | "target": "es2020"
7 | },
8 | "files": [
9 | "src/main.ts",
10 | "src/polyfills.ts"
11 | ],
12 | "include": [
13 | "src/**/*.d.ts"
14 | ]
15 | }
--------------------------------------------------------------------------------
/projects/mfe1/tsconfig.spec.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "../../out-tsc/spec",
5 | "types": [
6 | "jasmine",
7 | "node"
8 | ]
9 | },
10 | "files": [
11 | "src/test.ts",
12 | "src/polyfills.ts"
13 | ],
14 | "include": [
15 | "src/**/*.spec.ts",
16 | "src/**/*.d.ts"
17 | ]
18 | }
19 |
--------------------------------------------------------------------------------
/projects/mfe1/tslint.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tslint.json",
3 | "rules": {
4 | "directive-selector": [
5 | true,
6 | "attribute",
7 | "app",
8 | "camelCase"
9 | ],
10 | "component-selector": [
11 | true,
12 | "element",
13 | "app",
14 | "kebab-case"
15 | ]
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/projects/mfe1/webpack.config.js:
--------------------------------------------------------------------------------
1 | const { shareAll, withModuleFederationPlugin } = require('@angular-architects/module-federation/webpack');
2 |
3 | module.exports = withModuleFederationPlugin({
4 |
5 | name: 'mfe1',
6 |
7 | exposes: {
8 | './Download': './projects/mfe1/src/app/download.component.ts',
9 | './Upload': './projects/mfe1/src/app/upload.component.ts'
10 | },
11 |
12 | shared: {
13 | ...shareAll({ singleton: true, strictVersion: true, requiredVersion: 'auto' }),
14 | },
15 |
16 | });
17 |
--------------------------------------------------------------------------------
/projects/mfe1/webpack.prod.config.js:
--------------------------------------------------------------------------------
1 | module.exports = require('./webpack.config');
2 |
--------------------------------------------------------------------------------
/projects/mfe2/browserslist:
--------------------------------------------------------------------------------
1 | # This file is used by the build system to adjust CSS and JS output to support the specified browsers below.
2 | # For additional information regarding the format and rule options, please see:
3 | # https://github.com/browserslist/browserslist#queries
4 |
5 | # You can see what browsers were selected by your queries by running:
6 | # npx browserslist
7 |
8 | > 0.5%
9 | last 2 versions
10 | Firefox ESR
11 | not dead
12 | not IE 9-11 # For IE 9-11 support, remove 'not'.
--------------------------------------------------------------------------------
/projects/mfe2/e2e/protractor.conf.js:
--------------------------------------------------------------------------------
1 | // @ts-check
2 | // Protractor configuration file, see link for more information
3 | // https://github.com/angular/protractor/blob/master/lib/config.ts
4 |
5 | const { SpecReporter } = require('jasmine-spec-reporter');
6 |
7 | /**
8 | * @type { import("protractor").Config }
9 | */
10 | exports.config = {
11 | allScriptsTimeout: 11000,
12 | specs: [
13 | './src/**/*.e2e-spec.ts'
14 | ],
15 | capabilities: {
16 | browserName: 'chrome'
17 | },
18 | directConnect: true,
19 | baseUrl: 'http://localhost:4200/',
20 | framework: 'jasmine',
21 | jasmineNodeOpts: {
22 | showColors: true,
23 | defaultTimeoutInterval: 30000,
24 | print: function() {}
25 | },
26 | onPrepare() {
27 | require('ts-node').register({
28 | project: require('path').join(__dirname, './tsconfig.json')
29 | });
30 | jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } }));
31 | }
32 | };
--------------------------------------------------------------------------------
/projects/mfe2/e2e/src/app.e2e-spec.ts:
--------------------------------------------------------------------------------
1 | import { AppPage } from './app.po';
2 | import { browser, logging } from 'protractor';
3 |
4 | describe('workspace-project App', () => {
5 | let page: AppPage;
6 |
7 | beforeEach(() => {
8 | page = new AppPage();
9 | });
10 |
11 | it('should display welcome message', () => {
12 | page.navigateTo();
13 | expect(page.getTitleText()).toEqual('mfe1 app is running!');
14 | });
15 |
16 | afterEach(async () => {
17 | // Assert that there are no errors emitted from the browser
18 | const logs = await browser.manage().logs().get(logging.Type.BROWSER);
19 | expect(logs).not.toContain(jasmine.objectContaining({
20 | level: logging.Level.SEVERE,
21 | } as logging.Entry));
22 | });
23 | });
24 |
--------------------------------------------------------------------------------
/projects/mfe2/e2e/src/app.po.ts:
--------------------------------------------------------------------------------
1 | import { browser, by, element } from 'protractor';
2 |
3 | export class AppPage {
4 | navigateTo(): Promise {
5 | return browser.get(browser.baseUrl) as Promise;
6 | }
7 |
8 | getTitleText(): Promise {
9 | return element(by.css('app-root .content span')).getText() as Promise;
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/projects/mfe2/e2e/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../../tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "../../../out-tsc/e2e",
5 | "module": "commonjs",
6 | "target": "es5",
7 | "types": [
8 | "jasmine",
9 | "jasminewd2",
10 | "node"
11 | ]
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/projects/mfe2/karma.conf.js:
--------------------------------------------------------------------------------
1 | // Karma configuration file, see link for more information
2 | // https://karma-runner.github.io/1.0/config/configuration-file.html
3 |
4 | module.exports = function (config) {
5 | config.set({
6 | basePath: '',
7 | frameworks: ['jasmine', '@angular-devkit/build-angular'],
8 | plugins: [
9 | require('karma-jasmine'),
10 | require('karma-chrome-launcher'),
11 | require('karma-jasmine-html-reporter'),
12 | require('karma-coverage-istanbul-reporter'),
13 | require('@angular-devkit/build-angular/plugins/karma')
14 | ],
15 | client: {
16 | clearContext: false // leave Jasmine Spec Runner output visible in browser
17 | },
18 | coverageIstanbulReporter: {
19 | dir: require('path').join(__dirname, '../../coverage/mfe1'),
20 | reports: ['html', 'lcovonly', 'text-summary'],
21 | fixWebpackSourcePaths: true
22 | },
23 | reporters: ['progress', 'kjhtml'],
24 | port: 9876,
25 | colors: true,
26 | logLevel: config.LOG_INFO,
27 | autoWatch: true,
28 | browsers: ['Chrome'],
29 | singleRun: false,
30 | restartOnFileChange: true
31 | });
32 | };
33 |
--------------------------------------------------------------------------------
/projects/mfe2/src/app/ai-analyze.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit } from '@angular/core';
2 |
3 | @Component({
4 | standalone: true,
5 | selector: 'mfe2-ai-analyze',
6 | template: `
7 |
8 |

9 |
Analyze
10 |
11 | `
12 | })
13 | export class AiAnalyzeComponent implements OnInit {
14 | constructor() { }
15 |
16 | ngOnInit() { }
17 | }
--------------------------------------------------------------------------------
/projects/mfe2/src/app/analyze.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit } from '@angular/core';
2 |
3 | @Component({
4 | standalone: true,
5 | selector: 'mfe2-analyze',
6 | template: `
7 |
8 |

9 |
Analyze
10 |
11 | `
12 | })
13 | export class AnalyzeComponent implements OnInit {
14 | constructor() { }
15 |
16 | ngOnInit() { }
17 | }
--------------------------------------------------------------------------------
/projects/mfe2/src/app/app.component.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/manfredsteyer/module-federation-with-angular-dynamic-workflow-designer/02243b01c96e52e5257d9cf9dbbfd2beea858691/projects/mfe2/src/app/app.component.css
--------------------------------------------------------------------------------
/projects/mfe2/src/app/app.component.html:
--------------------------------------------------------------------------------
1 | mfe2
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/projects/mfe2/src/app/app.component.spec.ts:
--------------------------------------------------------------------------------
1 | import { TestBed, async } from '@angular/core/testing';
2 | import { AppComponent } from './app.component';
3 |
4 | describe('AppComponent', () => {
5 | beforeEach(async(() => {
6 | TestBed.configureTestingModule({
7 | declarations: [
8 | AppComponent
9 | ],
10 | }).compileComponents();
11 | }));
12 |
13 | it('should create the app', () => {
14 | const fixture = TestBed.createComponent(AppComponent);
15 | const app = fixture.componentInstance;
16 | expect(app).toBeTruthy();
17 | });
18 |
19 | it(`should have as title 'mfe2'`, () => {
20 | const fixture = TestBed.createComponent(AppComponent);
21 | const app = fixture.componentInstance;
22 | expect(app.title).toEqual('mfe2');
23 | });
24 |
25 | it('should render title', () => {
26 | const fixture = TestBed.createComponent(AppComponent);
27 | fixture.detectChanges();
28 | const compiled = fixture.nativeElement;
29 | expect(compiled.querySelector('.content span').textContent).toContain('mfe2 app is running!');
30 | });
31 | });
32 |
--------------------------------------------------------------------------------
/projects/mfe2/src/app/app.component.ts:
--------------------------------------------------------------------------------
1 | import { Component } from '@angular/core';
2 | import { AiAnalyzeComponent } from './ai-analyze.component';
3 | import { AnalyzeComponent } from './analyze.component';
4 | import { EnrichComponent } from './enrich.component';
5 |
6 | @Component({
7 | standalone: true,
8 | imports: [
9 | AnalyzeComponent,
10 | EnrichComponent,
11 | AiAnalyzeComponent,
12 | ],
13 | selector: 'app-root',
14 | templateUrl: 'app.component.html'
15 | })
16 | export class AppComponent {
17 | }
18 |
--------------------------------------------------------------------------------
/projects/mfe2/src/app/enrich.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit } from '@angular/core';
2 |
3 | @Component({
4 | standalone: true,
5 | selector: 'mfe2-enrich',
6 | template: `
7 |
8 |

9 |
Enrich
10 |
11 | `
12 | })
13 | export class EnrichComponent implements OnInit {
14 | constructor() { }
15 |
16 | ngOnInit() { }
17 | }
--------------------------------------------------------------------------------
/projects/mfe2/src/assets/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/manfredsteyer/module-federation-with-angular-dynamic-workflow-designer/02243b01c96e52e5257d9cf9dbbfd2beea858691/projects/mfe2/src/assets/.gitkeep
--------------------------------------------------------------------------------
/projects/mfe2/src/assets/analyze.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/manfredsteyer/module-federation-with-angular-dynamic-workflow-designer/02243b01c96e52e5257d9cf9dbbfd2beea858691/projects/mfe2/src/assets/analyze.png
--------------------------------------------------------------------------------
/projects/mfe2/src/assets/android.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/manfredsteyer/module-federation-with-angular-dynamic-workflow-designer/02243b01c96e52e5257d9cf9dbbfd2beea858691/projects/mfe2/src/assets/android.png
--------------------------------------------------------------------------------
/projects/mfe2/src/assets/android.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/manfredsteyer/module-federation-with-angular-dynamic-workflow-designer/02243b01c96e52e5257d9cf9dbbfd2beea858691/projects/mfe2/src/assets/android.webp
--------------------------------------------------------------------------------
/projects/mfe2/src/assets/angular.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/manfredsteyer/module-federation-with-angular-dynamic-workflow-designer/02243b01c96e52e5257d9cf9dbbfd2beea858691/projects/mfe2/src/assets/angular.png
--------------------------------------------------------------------------------
/projects/mfe2/src/assets/enrich.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/manfredsteyer/module-federation-with-angular-dynamic-workflow-designer/02243b01c96e52e5257d9cf9dbbfd2beea858691/projects/mfe2/src/assets/enrich.png
--------------------------------------------------------------------------------
/projects/mfe2/src/bootstrap.ts:
--------------------------------------------------------------------------------
1 | import { environment } from './environments/environment';
2 | import { enableProdMode } from '@angular/core';
3 | import { bootstrapApplication } from '@angular/platform-browser';
4 | import { AppComponent } from './app/app.component';
5 |
6 | if (environment.production) {
7 | enableProdMode();
8 | }
9 |
10 | bootstrapApplication(AppComponent, {
11 | providers: []
12 | });
13 |
--------------------------------------------------------------------------------
/projects/mfe2/src/environments/environment.prod.ts:
--------------------------------------------------------------------------------
1 | export const environment = {
2 | production: true
3 | };
4 |
--------------------------------------------------------------------------------
/projects/mfe2/src/environments/environment.ts:
--------------------------------------------------------------------------------
1 | // This file can be replaced during build by using the `fileReplacements` array.
2 | // `ng build --prod` replaces `environment.ts` with `environment.prod.ts`.
3 | // The list of file replacements can be found in `angular.json`.
4 |
5 | export const environment = {
6 | production: false
7 | };
8 |
9 | /*
10 | * For easier debugging in development mode, you can import the following file
11 | * to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`.
12 | *
13 | * This import should be commented out in production mode because it will have a negative impact
14 | * on performance if an error is thrown.
15 | */
16 | // import 'zone.js/dist/zone-error'; // Included with Angular CLI.
17 |
--------------------------------------------------------------------------------
/projects/mfe2/src/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/manfredsteyer/module-federation-with-angular-dynamic-workflow-designer/02243b01c96e52e5257d9cf9dbbfd2beea858691/projects/mfe2/src/favicon.ico
--------------------------------------------------------------------------------
/projects/mfe2/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Mfe1
6 |
7 |
8 |
9 |
10 |
11 |
12 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/projects/mfe2/src/main.ts:
--------------------------------------------------------------------------------
1 | import('./bootstrap')
2 | .catch(err => console.error(err));
3 |
--------------------------------------------------------------------------------
/projects/mfe2/src/polyfills.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * This file includes polyfills needed by Angular and is loaded before the app.
3 | * You can add your own extra polyfills to this file.
4 | *
5 | * This file is divided into 2 sections:
6 | * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers.
7 | * 2. Application imports. Files imported after ZoneJS that should be loaded before your main
8 | * file.
9 | *
10 | * The current setup is for so-called "evergreen" browsers; the last versions of browsers that
11 | * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera),
12 | * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile.
13 | *
14 | * Learn more in https://angular.io/guide/browser-support
15 | */
16 |
17 | /***************************************************************************************************
18 | * BROWSER POLYFILLS
19 | */
20 |
21 | /**
22 | * By default, zone.js will patch all possible macroTask and DomEvents
23 | * user can disable parts of macroTask/DomEvents patch by setting following flags
24 | * because those flags need to be set before `zone.js` being loaded, and webpack
25 | * will put import in the top of bundle, so user need to create a separate file
26 | * in this directory (for example: zone-flags.ts), and put the following flags
27 | * into that file, and then add the following code before importing zone.js.
28 | * import './zone-flags';
29 | *
30 | * The flags allowed in zone-flags.ts are listed here.
31 | *
32 | * The following flags will work for all browsers.
33 | *
34 | * (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame
35 | * (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick
36 | * (window as any).__zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames
37 | *
38 | * in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js
39 | * with the following flag, it will bypass `zone.js` patch for IE/Edge
40 | *
41 | * (window as any).__Zone_enable_cross_context_check = true;
42 | *
43 | */
44 |
45 | /***************************************************************************************************
46 | * Zone JS is required by default for Angular itself.
47 | */
48 | import 'zone.js/dist/zone'; // Included with Angular CLI.
49 |
50 |
51 | /***************************************************************************************************
52 | * APPLICATION IMPORTS
53 | */
54 |
--------------------------------------------------------------------------------
/projects/mfe2/src/styles.css:
--------------------------------------------------------------------------------
1 | /* You can add global styles to this file, and also import other style files */
2 |
--------------------------------------------------------------------------------
/projects/mfe2/src/test.ts:
--------------------------------------------------------------------------------
1 | // This file is required by karma.conf.js and loads recursively all the .spec and framework files
2 |
3 | import 'zone.js/dist/zone-testing';
4 | import { getTestBed } from '@angular/core/testing';
5 | import {
6 | BrowserDynamicTestingModule,
7 | platformBrowserDynamicTesting
8 | } from '@angular/platform-browser-dynamic/testing';
9 |
10 | declare const require: {
11 | context(path: string, deep?: boolean, filter?: RegExp): {
12 | keys(): string[];
13 | (id: string): T;
14 | };
15 | };
16 |
17 | // First, initialize the Angular testing environment.
18 | getTestBed().initTestEnvironment(
19 | BrowserDynamicTestingModule,
20 | platformBrowserDynamicTesting(), {
21 | teardown: { destroyAfterEach: false }
22 | }
23 | );
24 | // Then we find all the tests.
25 | const context = require.context('./', true, /\.spec\.ts$/);
26 | // And load the modules.
27 | context.keys().map(context);
28 |
--------------------------------------------------------------------------------
/projects/mfe2/tsconfig.app.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "../../out-tsc/app",
5 | "types": [],
6 | "target": "es2020"
7 | },
8 | "files": [
9 | "src/main.ts",
10 | "src/polyfills.ts"
11 | ],
12 | "include": [
13 | "src/**/*.d.ts"
14 | ]
15 | }
--------------------------------------------------------------------------------
/projects/mfe2/tsconfig.spec.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "../../out-tsc/spec",
5 | "types": [
6 | "jasmine",
7 | "node"
8 | ]
9 | },
10 | "files": [
11 | "src/test.ts",
12 | "src/polyfills.ts"
13 | ],
14 | "include": [
15 | "src/**/*.spec.ts",
16 | "src/**/*.d.ts"
17 | ]
18 | }
19 |
--------------------------------------------------------------------------------
/projects/mfe2/tslint.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tslint.json",
3 | "rules": {
4 | "directive-selector": [
5 | true,
6 | "attribute",
7 | "app",
8 | "camelCase"
9 | ],
10 | "component-selector": [
11 | true,
12 | "element",
13 | "app",
14 | "kebab-case"
15 | ]
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/projects/mfe2/webpack.config.js:
--------------------------------------------------------------------------------
1 | const { shareAll, withModuleFederationPlugin } = require('@angular-architects/module-federation/webpack');
2 |
3 | module.exports = withModuleFederationPlugin({
4 |
5 | name: 'mfe2',
6 |
7 | exposes: {
8 | './Analyze': './projects/mfe2/src/app/analyze.component.ts',
9 | './Enrich': './projects/mfe2/src/app/enrich.component.ts',
10 | './AiAnalyze': './projects/mfe2/src/app/ai-analyze.component.ts'
11 |
12 | },
13 |
14 | shared: {
15 | ...shareAll({ singleton: true, strictVersion: true, requiredVersion: 'auto' }),
16 | },
17 |
18 | });
19 |
--------------------------------------------------------------------------------
/projects/mfe2/webpack.prod.config.js:
--------------------------------------------------------------------------------
1 | module.exports = require('./webpack.config');
2 |
--------------------------------------------------------------------------------
/projects/shell/browserslist:
--------------------------------------------------------------------------------
1 | # This file is used by the build system to adjust CSS and JS output to support the specified browsers below.
2 | # For additional information regarding the format and rule options, please see:
3 | # https://github.com/browserslist/browserslist#queries
4 |
5 | # You can see what browsers were selected by your queries by running:
6 | # npx browserslist
7 |
8 | > 0.5%
9 | last 2 versions
10 | Firefox ESR
11 | not dead
12 | not IE 9-11 # For IE 9-11 support, remove 'not'.
--------------------------------------------------------------------------------
/projects/shell/e2e/protractor.conf.js:
--------------------------------------------------------------------------------
1 | // @ts-check
2 | // Protractor configuration file, see link for more information
3 | // https://github.com/angular/protractor/blob/master/lib/config.ts
4 |
5 | const { SpecReporter } = require('jasmine-spec-reporter');
6 |
7 | /**
8 | * @type { import("protractor").Config }
9 | */
10 | exports.config = {
11 | allScriptsTimeout: 11000,
12 | specs: [
13 | './src/**/*.e2e-spec.ts'
14 | ],
15 | capabilities: {
16 | browserName: 'chrome'
17 | },
18 | directConnect: true,
19 | baseUrl: 'http://localhost:4200/',
20 | framework: 'jasmine',
21 | jasmineNodeOpts: {
22 | showColors: true,
23 | defaultTimeoutInterval: 30000,
24 | print: function() {}
25 | },
26 | onPrepare() {
27 | require('ts-node').register({
28 | project: require('path').join(__dirname, './tsconfig.json')
29 | });
30 | jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } }));
31 | }
32 | };
--------------------------------------------------------------------------------
/projects/shell/e2e/src/app.e2e-spec.ts:
--------------------------------------------------------------------------------
1 | import { AppPage } from './app.po';
2 | import { browser, logging } from 'protractor';
3 |
4 | describe('workspace-project App', () => {
5 | let page: AppPage;
6 |
7 | beforeEach(() => {
8 | page = new AppPage();
9 | });
10 |
11 | it('should display welcome message', () => {
12 | page.navigateTo();
13 | expect(page.getTitleText()).toEqual('shell app is running!');
14 | });
15 |
16 | afterEach(async () => {
17 | // Assert that there are no errors emitted from the browser
18 | const logs = await browser.manage().logs().get(logging.Type.BROWSER);
19 | expect(logs).not.toContain(jasmine.objectContaining({
20 | level: logging.Level.SEVERE,
21 | } as logging.Entry));
22 | });
23 | });
24 |
--------------------------------------------------------------------------------
/projects/shell/e2e/src/app.po.ts:
--------------------------------------------------------------------------------
1 | import { browser, by, element } from 'protractor';
2 |
3 | export class AppPage {
4 | navigateTo(): Promise {
5 | return browser.get(browser.baseUrl) as Promise;
6 | }
7 |
8 | getTitleText(): Promise {
9 | return element(by.css('app-root .content span')).getText() as Promise;
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/projects/shell/e2e/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../../tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "../../../out-tsc/e2e",
5 | "module": "commonjs",
6 | "target": "es5",
7 | "types": [
8 | "jasmine",
9 | "jasminewd2",
10 | "node"
11 | ]
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/projects/shell/karma.conf.js:
--------------------------------------------------------------------------------
1 | // Karma configuration file, see link for more information
2 | // https://karma-runner.github.io/1.0/config/configuration-file.html
3 |
4 | module.exports = function (config) {
5 | config.set({
6 | basePath: '',
7 | frameworks: ['jasmine', '@angular-devkit/build-angular'],
8 | plugins: [
9 | require('karma-jasmine'),
10 | require('karma-chrome-launcher'),
11 | require('karma-jasmine-html-reporter'),
12 | require('karma-coverage-istanbul-reporter'),
13 | require('@angular-devkit/build-angular/plugins/karma')
14 | ],
15 | client: {
16 | clearContext: false // leave Jasmine Spec Runner output visible in browser
17 | },
18 | coverageIstanbulReporter: {
19 | dir: require('path').join(__dirname, '../../coverage/shell'),
20 | reports: ['html', 'lcovonly', 'text-summary'],
21 | fixWebpackSourcePaths: true
22 | },
23 | reporters: ['progress', 'kjhtml'],
24 | port: 9876,
25 | colors: true,
26 | logLevel: config.LOG_INFO,
27 | autoWatch: true,
28 | browsers: ['Chrome'],
29 | singleRun: false,
30 | restartOnFileChange: true
31 | });
32 | };
33 |
--------------------------------------------------------------------------------
/projects/shell/src/app/app.component.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/manfredsteyer/module-federation-with-angular-dynamic-workflow-designer/02243b01c96e52e5257d9cf9dbbfd2beea858691/projects/shell/src/app/app.component.css
--------------------------------------------------------------------------------
/projects/shell/src/app/app.component.html:
--------------------------------------------------------------------------------
1 |
6 |
7 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/projects/shell/src/app/app.component.ts:
--------------------------------------------------------------------------------
1 | import { PluginOptions } from './plugins/plugin';
2 | import { Component, OnInit } from '@angular/core';
3 | import { LookupService } from './plugins/lookup.service';
4 | import { ConfigComponent } from './config/config.component';
5 | import { PluginProxyComponent } from './plugins/plugin-proxy.component';
6 | import { CommonModule } from '@angular/common';
7 |
8 | @Component({
9 | standalone: true,
10 | imports: [
11 | ConfigComponent,
12 | PluginProxyComponent,
13 | CommonModule,
14 | ],
15 | selector: 'app-root',
16 | templateUrl: './app.component.html'
17 | })
18 | export class AppComponent implements OnInit {
19 |
20 | plugins: PluginOptions[] = [];
21 | workflow: PluginOptions[] = [];
22 | showConfig = false;
23 |
24 | constructor(
25 | private lookupService: LookupService) {
26 | }
27 |
28 | async ngOnInit(): Promise {
29 | this.plugins = await this.lookupService.lookup();
30 | }
31 |
32 | add(plugin: PluginOptions): void {
33 | this.workflow.push(plugin);
34 | }
35 |
36 | toggle(): void {
37 | this.showConfig = !this.showConfig;
38 | }
39 | }
40 |
41 |
--------------------------------------------------------------------------------
/projects/shell/src/app/config/config.component.html:
--------------------------------------------------------------------------------
1 | Config
2 |
3 | {{ config | json }}
--------------------------------------------------------------------------------
/projects/shell/src/app/config/config.component.spec.ts:
--------------------------------------------------------------------------------
1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing';
2 |
3 | import { ConfigComponent } from './config.component';
4 |
5 | describe('ConfigComponent', () => {
6 | let component: ConfigComponent;
7 | let fixture: ComponentFixture;
8 |
9 | beforeEach(async(() => {
10 | TestBed.configureTestingModule({
11 | declarations: [ ConfigComponent ]
12 | })
13 | .compileComponents();
14 | }));
15 |
16 | beforeEach(() => {
17 | fixture = TestBed.createComponent(ConfigComponent);
18 | component = fixture.componentInstance;
19 | fixture.detectChanges();
20 | });
21 |
22 | it('should create', () => {
23 | expect(component).toBeTruthy();
24 | });
25 | });
26 |
--------------------------------------------------------------------------------
/projects/shell/src/app/config/config.component.ts:
--------------------------------------------------------------------------------
1 | import { CommonModule } from '@angular/common';
2 | import { Component, OnInit } from '@angular/core';
3 | import { LookupService } from '../plugins/lookup.service';
4 | import { PluginOptions } from '../plugins/plugin';
5 |
6 | @Component({
7 | standalone: true,
8 | imports: [
9 | CommonModule
10 | ],
11 | selector: 'app-config',
12 | templateUrl: './config.component.html'
13 | })
14 | export class ConfigComponent implements OnInit {
15 |
16 | constructor(private lookupService: LookupService) { }
17 |
18 | config: PluginOptions[];
19 |
20 | async ngOnInit() {
21 | this.config = await this.lookupService.lookup();
22 | }
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/projects/shell/src/app/home/home.component.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/manfredsteyer/module-federation-with-angular-dynamic-workflow-designer/02243b01c96e52e5257d9cf9dbbfd2beea858691/projects/shell/src/app/home/home.component.css
--------------------------------------------------------------------------------
/projects/shell/src/app/home/home.component.html:
--------------------------------------------------------------------------------
1 | Welcome!
--------------------------------------------------------------------------------
/projects/shell/src/app/home/home.component.spec.ts:
--------------------------------------------------------------------------------
1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing';
2 |
3 | import { HomeComponent } from './home.component';
4 |
5 | describe('HomeComponent', () => {
6 | let component: HomeComponent;
7 | let fixture: ComponentFixture;
8 |
9 | beforeEach(async(() => {
10 | TestBed.configureTestingModule({
11 | declarations: [ HomeComponent ]
12 | })
13 | .compileComponents();
14 | }));
15 |
16 | beforeEach(() => {
17 | fixture = TestBed.createComponent(HomeComponent);
18 | component = fixture.componentInstance;
19 | fixture.detectChanges();
20 | });
21 |
22 | it('should create', () => {
23 | expect(component).toBeTruthy();
24 | });
25 | });
26 |
--------------------------------------------------------------------------------
/projects/shell/src/app/home/home.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit } from '@angular/core';
2 |
3 | @Component({
4 | standalone: true,
5 | selector: 'app-home',
6 | templateUrl: './home.component.html'
7 | })
8 | export class HomeComponent implements OnInit {
9 |
10 | constructor() { }
11 |
12 | ngOnInit() {
13 | }
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/projects/shell/src/app/plugins/lookup.service.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from '@angular/core';
2 | import { PluginOptions } from './plugin';
3 |
4 | @Injectable({ providedIn: 'root' })
5 | export class LookupService {
6 | lookup(): Promise {
7 | return Promise.resolve([
8 | {
9 | type: 'module',
10 | remoteEntry: 'http://localhost:4201/remoteEntry.js',
11 | exposedModule: './Download',
12 |
13 | displayName: 'Download',
14 | componentName: 'DownloadComponent'
15 | },
16 | {
17 | type: 'module',
18 | remoteEntry: 'http://localhost:4201/remoteEntry.js',
19 | exposedModule: './Upload',
20 |
21 | displayName: 'Upload',
22 | componentName: 'UploadComponent'
23 | },
24 | {
25 | type: 'module',
26 | remoteEntry: 'http://localhost:4202/remoteEntry.js',
27 | exposedModule: './Analyze',
28 |
29 | displayName: 'Analyze',
30 | componentName: 'AnalyzeComponent'
31 | },
32 | {
33 | type: 'module',
34 | remoteEntry: 'http://localhost:4202/remoteEntry.js',
35 | exposedModule: './Enrich',
36 |
37 | displayName: 'Enrich',
38 | componentName: 'EnrichComponent'
39 | }
40 | ] as PluginOptions[]);
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/projects/shell/src/app/plugins/plugin-proxy.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, Input, OnChanges, ViewChild, ViewContainerRef, ComponentFactoryResolver, Injector, Type } from '@angular/core';
2 | import { loadRemoteModule } from '@angular-architects/module-federation';
3 | import { PluginOptions } from './plugin';
4 |
5 | @Component({
6 | standalone: true,
7 | selector: 'plugin-proxy',
8 | template: `
9 |
10 | `
11 | })
12 | export class PluginProxyComponent implements OnChanges {
13 | @ViewChild('placeHolder', { read: ViewContainerRef, static: true })
14 | viewContainer: ViewContainerRef;
15 |
16 | constructor() { }
17 |
18 | @Input() options: PluginOptions;
19 |
20 | async ngOnChanges() {
21 | this.viewContainer.clear();
22 |
23 | const Component = await loadRemoteModule(this.options)
24 | .then(m => m[this.options.componentName]);
25 |
26 | this.viewContainer.createComponent(Component);
27 | }
28 | }
29 |
30 |
--------------------------------------------------------------------------------
/projects/shell/src/app/plugins/plugin.ts:
--------------------------------------------------------------------------------
1 | import { LoadRemoteModuleOptions } from '@angular-architects/module-federation';
2 |
3 | export type PluginOptions = LoadRemoteModuleOptions & {
4 | displayName: string;
5 | componentName: string;
6 | };
7 |
--------------------------------------------------------------------------------
/projects/shell/src/assets/angular.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/manfredsteyer/module-federation-with-angular-dynamic-workflow-designer/02243b01c96e52e5257d9cf9dbbfd2beea858691/projects/shell/src/assets/angular.png
--------------------------------------------------------------------------------
/projects/shell/src/bootstrap.ts:
--------------------------------------------------------------------------------
1 | import { environment } from './environments/environment';
2 | import { enableProdMode } from '@angular/core';
3 | import { bootstrapApplication } from '@angular/platform-browser';
4 | import { AppComponent } from './app/app.component';
5 |
6 | if (environment.production) {
7 | enableProdMode();
8 | }
9 |
10 | bootstrapApplication(AppComponent, {
11 | providers: [
12 | // provideRoutes(APP_ROUTES)
13 | ]
14 | });
15 |
--------------------------------------------------------------------------------
/projects/shell/src/environments/environment.prod.ts:
--------------------------------------------------------------------------------
1 | export const environment = {
2 | production: true
3 | };
4 |
--------------------------------------------------------------------------------
/projects/shell/src/environments/environment.ts:
--------------------------------------------------------------------------------
1 | // This file can be replaced during build by using the `fileReplacements` array.
2 | // `ng build --prod` replaces `environment.ts` with `environment.prod.ts`.
3 | // The list of file replacements can be found in `angular.json`.
4 |
5 | export const environment = {
6 | production: false
7 | };
8 |
9 | /*
10 | * For easier debugging in development mode, you can import the following file
11 | * to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`.
12 | *
13 | * This import should be commented out in production mode because it will have a negative impact
14 | * on performance if an error is thrown.
15 | */
16 | // import 'zone.js/dist/zone-error'; // Included with Angular CLI.
17 |
--------------------------------------------------------------------------------
/projects/shell/src/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/manfredsteyer/module-federation-with-angular-dynamic-workflow-designer/02243b01c96e52e5257d9cf9dbbfd2beea858691/projects/shell/src/favicon.ico
--------------------------------------------------------------------------------
/projects/shell/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Shell
6 |
7 |
8 |
9 |
10 |
11 |
12 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
--------------------------------------------------------------------------------
/projects/shell/src/main.ts:
--------------------------------------------------------------------------------
1 | import { loadRemoteEntry } from '@angular-architects/module-federation';
2 |
3 | Promise.all([
4 | loadRemoteEntry({ type: 'module', remoteEntry: 'http://localhost:4201/remoteEntry.js'}),
5 | loadRemoteEntry({ type: 'module', remoteEntry: 'http://localhost:4202/remoteEntry.js'})
6 | ])
7 | .then(() => import('./bootstrap'))
8 | .catch(err => console.error('error', err));
9 |
10 |
--------------------------------------------------------------------------------
/projects/shell/src/polyfills.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * This file includes polyfills needed by Angular and is loaded before the app.
3 | * You can add your own extra polyfills to this file.
4 | *
5 | * This file is divided into 2 sections:
6 | * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers.
7 | * 2. Application imports. Files imported after ZoneJS that should be loaded before your main
8 | * file.
9 | *
10 | * The current setup is for so-called "evergreen" browsers; the last versions of browsers that
11 | * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera),
12 | * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile.
13 | *
14 | * Learn more in https://angular.io/guide/browser-support
15 | */
16 |
17 | /***************************************************************************************************
18 | * BROWSER POLYFILLS
19 | */
20 |
21 | /**
22 | * By default, zone.js will patch all possible macroTask and DomEvents
23 | * user can disable parts of macroTask/DomEvents patch by setting following flags
24 | * because those flags need to be set before `zone.js` being loaded, and webpack
25 | * will put import in the top of bundle, so user need to create a separate file
26 | * in this directory (for example: zone-flags.ts), and put the following flags
27 | * into that file, and then add the following code before importing zone.js.
28 | * import './zone-flags';
29 | *
30 | * The flags allowed in zone-flags.ts are listed here.
31 | *
32 | * The following flags will work for all browsers.
33 | *
34 | * (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame
35 | * (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick
36 | * (window as any).__zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames
37 | *
38 | * in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js
39 | * with the following flag, it will bypass `zone.js` patch for IE/Edge
40 | *
41 | * (window as any).__Zone_enable_cross_context_check = true;
42 | *
43 | */
44 |
45 | /***************************************************************************************************
46 | * Zone JS is required by default for Angular itself.
47 | */
48 | import 'zone.js/dist/zone'; // Included with Angular CLI.
49 |
50 |
51 | /***************************************************************************************************
52 | * APPLICATION IMPORTS
53 | */
54 |
--------------------------------------------------------------------------------
/projects/shell/src/styles.css:
--------------------------------------------------------------------------------
1 | /* You can add global styles to this file, and also import other style files */
2 |
--------------------------------------------------------------------------------
/projects/shell/src/test.ts:
--------------------------------------------------------------------------------
1 | // This file is required by karma.conf.js and loads recursively all the .spec and framework files
2 |
3 | import 'zone.js/dist/zone-testing';
4 | import { getTestBed } from '@angular/core/testing';
5 | import {
6 | BrowserDynamicTestingModule,
7 | platformBrowserDynamicTesting
8 | } from '@angular/platform-browser-dynamic/testing';
9 |
10 | declare const require: {
11 | context(path: string, deep?: boolean, filter?: RegExp): {
12 | keys(): string[];
13 | (id: string): T;
14 | };
15 | };
16 |
17 | // First, initialize the Angular testing environment.
18 | getTestBed().initTestEnvironment(
19 | BrowserDynamicTestingModule,
20 | platformBrowserDynamicTesting(), {
21 | teardown: { destroyAfterEach: false }
22 | }
23 | );
24 | // Then we find all the tests.
25 | const context = require.context('./', true, /\.spec\.ts$/);
26 | // And load the modules.
27 | context.keys().map(context);
28 |
--------------------------------------------------------------------------------
/projects/shell/tsconfig.app.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "../../out-tsc/app",
5 | "types": [],
6 | "target": "es2020"
7 | },
8 | "files": [
9 | "src/main.ts",
10 | "src/polyfills.ts"
11 | ],
12 | "include": [
13 | "src/**/*.d.ts"
14 | ]
15 | }
--------------------------------------------------------------------------------
/projects/shell/tsconfig.spec.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "../../out-tsc/spec",
5 | "types": [
6 | "jasmine",
7 | "node"
8 | ]
9 | },
10 | "files": [
11 | "src/test.ts",
12 | "src/polyfills.ts"
13 | ],
14 | "include": [
15 | "src/**/*.spec.ts",
16 | "src/**/*.d.ts"
17 | ]
18 | }
19 |
--------------------------------------------------------------------------------
/projects/shell/tslint.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tslint.json",
3 | "rules": {
4 | "directive-selector": [
5 | true,
6 | "attribute",
7 | "app",
8 | "camelCase"
9 | ],
10 | "component-selector": [
11 | true,
12 | "element",
13 | "app",
14 | "kebab-case"
15 | ]
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/projects/shell/webpack.config.js:
--------------------------------------------------------------------------------
1 | const { shareAll, withModuleFederationPlugin } = require('@angular-architects/module-federation/webpack');
2 |
3 | module.exports = withModuleFederationPlugin({
4 |
5 | shared: {
6 | ...shareAll({ singleton: true, strictVersion: true, requiredVersion: 'auto' }),
7 | },
8 |
9 | });
10 |
--------------------------------------------------------------------------------
/projects/shell/webpack.config.old.js:
--------------------------------------------------------------------------------
1 | const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin");
2 | const mf = require("@angular-architects/module-federation/webpack");
3 | const path = require("path");
4 | const share = mf.share;
5 |
6 | const sharedMappings = new mf.SharedMappings();
7 | sharedMappings.register(
8 | path.join(__dirname, '../../tsconfig.json'),
9 | [/* mapped paths to share */]);
10 |
11 | module.exports = {
12 | output: {
13 | uniqueName: "shell",
14 | publicPath: "auto"
15 | },
16 | optimization: {
17 | runtimeChunk: false
18 | },
19 | resolve: {
20 | alias: {
21 | ...sharedMappings.getAliases(),
22 | }
23 | },
24 | experiments: {
25 | outputModule: true
26 | },
27 | plugins: [
28 | new ModuleFederationPlugin({
29 |
30 | library: { type: "module" },
31 |
32 | name: "shell",
33 | filename: "remoteEntry.js",
34 | exposes: { },
35 |
36 | shared: share({
37 | "@angular/core": { singleton: true, strictVersion: true, requiredVersion: 'auto' },
38 | "@angular/common": { singleton: true, strictVersion: true, requiredVersion: 'auto' },
39 | "@angular/common/http": { singleton: true, strictVersion: true, requiredVersion: 'auto' },
40 | "@angular/router": { singleton: true, strictVersion: true, requiredVersion: 'auto' },
41 |
42 | ...sharedMappings.getDescriptors()
43 | })
44 |
45 | }),
46 | sharedMappings.getPlugin()
47 | ],
48 | };
49 |
--------------------------------------------------------------------------------
/projects/shell/webpack.prod.config.js:
--------------------------------------------------------------------------------
1 | module.exports = require('./webpack.config');
2 |
--------------------------------------------------------------------------------
/projects/shell/webpack.prod.config.old.js:
--------------------------------------------------------------------------------
1 | module.exports = require('./webpack.config');
2 |
--------------------------------------------------------------------------------
/result.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/manfredsteyer/module-federation-with-angular-dynamic-workflow-designer/02243b01c96e52e5257d9cf9dbbfd2beea858691/result.png
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compileOnSave": false,
3 | "compilerOptions": {
4 | "baseUrl": "./",
5 | "outDir": "./dist/out-tsc",
6 | "sourceMap": true,
7 | "declaration": false,
8 | "downlevelIteration": true,
9 | "experimentalDecorators": true,
10 | "module": "ES2020",
11 | "allowJs": true,
12 | "moduleResolution": "node",
13 | "importHelpers": false,
14 | "target": "ES2020",
15 | "lib": [
16 | "es2018",
17 | "dom"
18 | ]
19 | }
20 | }
--------------------------------------------------------------------------------
/tslint.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "tslint:recommended",
3 | "rulesDirectory": [
4 | "codelyzer"
5 | ],
6 | "rules": {
7 | "align": {
8 | "options": [
9 | "parameters",
10 | "statements"
11 | ]
12 | },
13 | "array-type": false,
14 | "arrow-return-shorthand": true,
15 | "curly": true,
16 | "deprecation": {
17 | "severity": "warning"
18 | },
19 | "eofline": true,
20 | "import-blacklist": [
21 | true,
22 | "rxjs/Rx"
23 | ],
24 | "import-spacing": true,
25 | "indent": {
26 | "options": [
27 | "spaces"
28 | ]
29 | },
30 | "max-classes-per-file": false,
31 | "max-line-length": [
32 | true,
33 | 140
34 | ],
35 | "member-ordering": [
36 | true,
37 | {
38 | "order": [
39 | "static-field",
40 | "instance-field",
41 | "static-method",
42 | "instance-method"
43 | ]
44 | }
45 | ],
46 | "no-console": [
47 | true,
48 | "debug",
49 | "info",
50 | "time",
51 | "timeEnd",
52 | "trace"
53 | ],
54 | "no-empty": false,
55 | "no-inferrable-types": [
56 | true,
57 | "ignore-params"
58 | ],
59 | "no-non-null-assertion": true,
60 | "no-redundant-jsdoc": true,
61 | "no-switch-case-fall-through": true,
62 | "no-var-requires": false,
63 | "object-literal-key-quotes": [
64 | true,
65 | "as-needed"
66 | ],
67 | "quotemark": [
68 | true,
69 | "single"
70 | ],
71 | "semicolon": {
72 | "options": [
73 | "always"
74 | ]
75 | },
76 | "space-before-function-paren": {
77 | "options": {
78 | "anonymous": "never",
79 | "asyncArrow": "always",
80 | "constructor": "never",
81 | "method": "never",
82 | "named": "never"
83 | }
84 | },
85 | "typedef-whitespace": {
86 | "options": [
87 | {
88 | "call-signature": "nospace",
89 | "index-signature": "nospace",
90 | "parameter": "nospace",
91 | "property-declaration": "nospace",
92 | "variable-declaration": "nospace"
93 | },
94 | {
95 | "call-signature": "onespace",
96 | "index-signature": "onespace",
97 | "parameter": "onespace",
98 | "property-declaration": "onespace",
99 | "variable-declaration": "onespace"
100 | }
101 | ]
102 | },
103 | "variable-name": {
104 | "options": [
105 | "ban-keywords",
106 | "check-format",
107 | "allow-pascal-case"
108 | ]
109 | },
110 | "whitespace": {
111 | "options": [
112 | "check-branch",
113 | "check-decl",
114 | "check-operator",
115 | "check-separator",
116 | "check-type",
117 | "check-typecast"
118 | ]
119 | },
120 | "component-class-suffix": true,
121 | "contextual-lifecycle": true,
122 | "directive-class-suffix": true,
123 | "no-conflicting-lifecycle": true,
124 | "no-host-metadata-property": true,
125 | "no-input-rename": true,
126 | "no-inputs-metadata-property": true,
127 | "no-output-native": true,
128 | "no-output-on-prefix": true,
129 | "no-output-rename": true,
130 | "no-outputs-metadata-property": true,
131 | "template-banana-in-box": true,
132 | "template-no-negated-async": true,
133 | "use-lifecycle-interface": true,
134 | "use-pipe-transform-interface": true
135 | }
136 | }
137 |
--------------------------------------------------------------------------------