├── .editorconfig ├── .eslintrc.json ├── .gitignore ├── .npmrc ├── .prettierignore ├── .prettierrc ├── .vscode └── extensions.json ├── README.md ├── angular.json ├── apps ├── .gitkeep ├── calendar-e2e │ ├── .eslintrc.json │ ├── cypress.json │ ├── src │ │ ├── fixtures │ │ │ └── example.json │ │ ├── integration │ │ │ └── app.spec.ts │ │ ├── plugins │ │ │ └── index.js │ │ └── support │ │ │ ├── app.po.ts │ │ │ ├── commands.ts │ │ │ └── index.ts │ ├── tsconfig.e2e.json │ └── tsconfig.json ├── calendar │ ├── .browserslistrc │ ├── .eslintrc.json │ ├── jest.config.js │ ├── src │ │ ├── app │ │ │ ├── app.component.html │ │ │ ├── app.component.scss │ │ │ ├── app.component.spec.ts │ │ │ ├── app.component.ts │ │ │ ├── app.module.ts │ │ │ └── calendar │ │ │ │ ├── calendar.component.css │ │ │ │ ├── calendar.component.html │ │ │ │ ├── calendar.component.spec.ts │ │ │ │ ├── calendar.component.ts │ │ │ │ └── calendar.module.ts │ │ ├── assets │ │ │ └── .gitkeep │ │ ├── bootstrap.ts │ │ ├── environments │ │ │ ├── environment.prod.ts │ │ │ └── environment.ts │ │ ├── favicon.ico │ │ ├── index.html │ │ ├── main.ts │ │ ├── polyfills.ts │ │ ├── styles.scss │ │ └── test-setup.ts │ ├── tsconfig.app.json │ ├── tsconfig.editor.json │ ├── tsconfig.json │ ├── tsconfig.spec.json │ ├── webpack.config.js │ └── webpack.prod.config.js ├── mailbox-e2e │ ├── .eslintrc.json │ ├── cypress.json │ ├── src │ │ ├── fixtures │ │ │ └── example.json │ │ ├── integration │ │ │ └── app.spec.ts │ │ ├── plugins │ │ │ └── index.js │ │ └── support │ │ │ ├── app.po.ts │ │ │ ├── commands.ts │ │ │ └── index.ts │ ├── tsconfig.e2e.json │ └── tsconfig.json ├── mailbox │ ├── .browserslistrc │ ├── .eslintrc.json │ ├── jest.config.js │ ├── src │ │ ├── app │ │ │ ├── app.component.html │ │ │ ├── app.component.scss │ │ │ ├── app.component.spec.ts │ │ │ ├── app.component.ts │ │ │ ├── app.module.ts │ │ │ └── mailbox │ │ │ │ ├── mailbox-routing.module.ts │ │ │ │ ├── mailbox.component.css │ │ │ │ ├── mailbox.component.html │ │ │ │ ├── mailbox.component.spec.ts │ │ │ │ ├── mailbox.component.ts │ │ │ │ └── mailbox.module.ts │ │ ├── assets │ │ │ └── .gitkeep │ │ ├── bootstrap.ts │ │ ├── environments │ │ │ ├── environment.prod.ts │ │ │ └── environment.ts │ │ ├── favicon.ico │ │ ├── index.html │ │ ├── main.ts │ │ ├── polyfills.ts │ │ ├── styles.scss │ │ └── test-setup.ts │ ├── tsconfig.app.json │ ├── tsconfig.editor.json │ ├── tsconfig.json │ ├── tsconfig.spec.json │ ├── webpack.config.js │ └── webpack.prod.config.js ├── shell-e2e │ ├── .eslintrc.json │ ├── cypress.json │ ├── src │ │ ├── fixtures │ │ │ └── example.json │ │ ├── integration │ │ │ └── app.spec.ts │ │ ├── plugins │ │ │ └── index.js │ │ └── support │ │ │ ├── app.po.ts │ │ │ ├── commands.ts │ │ │ └── index.ts │ ├── tsconfig.e2e.json │ └── tsconfig.json └── shell │ ├── .browserslistrc │ ├── .eslintrc.json │ ├── jest.config.js │ ├── src │ ├── app │ │ ├── app.component.html │ │ ├── app.component.scss │ │ ├── app.component.spec.ts │ │ ├── app.component.ts │ │ ├── app.module.ts │ │ └── typed.d.ts │ ├── assets │ │ └── .gitkeep │ ├── bootstrap.ts │ ├── environments │ │ ├── environment.prod.ts │ │ └── environment.ts │ ├── favicon.ico │ ├── index.html │ ├── main.ts │ ├── polyfills.ts │ ├── styles.scss │ └── test-setup.ts │ ├── tsconfig.app.json │ ├── tsconfig.editor.json │ ├── tsconfig.json │ ├── tsconfig.spec.json │ ├── webpack.config.js │ └── webpack.prod.config.js ├── decorate-angular-cli.js ├── jest.config.js ├── jest.preset.js ├── libs └── .gitkeep ├── nx.json ├── package-lock.json ├── package.json ├── tools ├── generators │ └── .gitkeep └── tsconfig.tools.json └── tsconfig.base.json /.editorconfig: -------------------------------------------------------------------------------- 1 | # Editor configuration, see http://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 | [*.md] 12 | max_line_length = off 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "root": true, 3 | "ignorePatterns": ["**/*"], 4 | "plugins": ["@nrwl/nx"], 5 | "overrides": [ 6 | { 7 | "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], 8 | "rules": { 9 | "@nrwl/nx/enforce-module-boundaries": [ 10 | "error", 11 | { 12 | "enforceBuildableLibDependency": true, 13 | "allow": [], 14 | "depConstraints": [ 15 | { 16 | "sourceTag": "*", 17 | "onlyDependOnLibsWithTags": ["*"] 18 | } 19 | ] 20 | } 21 | ] 22 | } 23 | }, 24 | { 25 | "files": ["*.ts", "*.tsx"], 26 | "extends": ["plugin:@nrwl/nx/typescript"], 27 | "rules": {} 28 | }, 29 | { 30 | "files": ["*.js", "*.jsx"], 31 | "extends": ["plugin:@nrwl/nx/javascript"], 32 | "rules": {} 33 | } 34 | ] 35 | } 36 | -------------------------------------------------------------------------------- /.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 | /.sass-cache 29 | /connect.lock 30 | /coverage 31 | /libpeerconnection.log 32 | npm-debug.log 33 | yarn-error.log 34 | testem.log 35 | /typings 36 | 37 | # System Files 38 | .DS_Store 39 | Thumbs.db 40 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | registry=https://registry.npmjs.org -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | # Add files here to ignore them from prettier formatting 2 | 3 | /dist 4 | /coverage 5 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true 3 | } -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "angular.ng-template", 4 | "nrwl.angular-console", 5 | "esbenp.prettier-vscode", 6 | "firsttris.vscode-jest-runner", 7 | "dbaeumer.vscode-eslint" 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Micro-Frontends with Nx, Webpack Module Federation and Angular 2 | 3 | ## Presentation 4 | https://docs.google.com/presentation/d/1Bm43te2cDjGuaL0itGh-b_v019XV-ynlq-B7Xeojccw/edit?usp=sharing 5 | ## Demo 6 | 7 | Install dependencies: 8 | 9 | ```sh 10 | npm i 11 | ``` 12 | 13 | Run remote apps first 14 | 15 | ```sh 16 | npm run start:mailbox 17 | npm run start:calendar 18 | 19 | ``` 20 | 21 | Run shell app 22 | 23 | ```sh 24 | npm run start:shell 25 | ``` 26 | -------------------------------------------------------------------------------- /angular.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 1, 3 | "projects": { 4 | "calendar": { 5 | "projectType": "application", 6 | "root": "apps/calendar", 7 | "sourceRoot": "apps/calendar/src", 8 | "prefix": "mfes", 9 | "architect": { 10 | "build": { 11 | "builder": "@angular-builders/custom-webpack:browser", 12 | "outputs": ["{options.outputPath}"], 13 | "options": { 14 | "outputPath": "dist/apps/calendar", 15 | "index": "apps/calendar/src/index.html", 16 | "main": "apps/calendar/src/main.ts", 17 | "polyfills": "apps/calendar/src/polyfills.ts", 18 | "tsConfig": "apps/calendar/tsconfig.app.json", 19 | "inlineStyleLanguage": "scss", 20 | "assets": [ 21 | "apps/calendar/src/favicon.ico", 22 | "apps/calendar/src/assets" 23 | ], 24 | "styles": ["apps/calendar/src/styles.scss"], 25 | "scripts": [] 26 | }, 27 | "configurations": { 28 | "production": { 29 | "budgets": [ 30 | { 31 | "type": "initial", 32 | "maximumWarning": "500kb", 33 | "maximumError": "1mb" 34 | }, 35 | { 36 | "type": "anyComponentStyle", 37 | "maximumWarning": "2kb", 38 | "maximumError": "4kb" 39 | } 40 | ], 41 | "fileReplacements": [ 42 | { 43 | "replace": "apps/calendar/src/environments/environment.ts", 44 | "with": "apps/calendar/src/environments/environment.prod.ts" 45 | } 46 | ], 47 | "outputHashing": "all", 48 | "customWebpackConfig": { 49 | "path": "apps/calendar/webpack.config.js" 50 | } 51 | }, 52 | "development": { 53 | "buildOptimizer": false, 54 | "optimization": false, 55 | "vendorChunk": true, 56 | "extractLicenses": false, 57 | "sourceMap": true, 58 | "namedChunks": true, 59 | "customWebpackConfig": { 60 | "path": "apps/calendar/webpack.prod.config.js" 61 | } 62 | } 63 | }, 64 | "defaultConfiguration": "production" 65 | }, 66 | "serve": { 67 | "builder": "@angular-builders/custom-webpack:dev-server", 68 | "configurations": { 69 | "production": { 70 | "browserTarget": "calendar:build:production" 71 | }, 72 | "development": { 73 | "browserTarget": "calendar:build:development" 74 | } 75 | }, 76 | "defaultConfiguration": "development" 77 | }, 78 | "extract-i18n": { 79 | "builder": "@angular-devkit/build-angular:extract-i18n", 80 | "options": { 81 | "browserTarget": "calendar:build" 82 | } 83 | }, 84 | "lint": { 85 | "builder": "@nrwl/linter:eslint", 86 | "options": { 87 | "lintFilePatterns": [ 88 | "apps/calendar/src/**/*.ts", 89 | "apps/calendar/src/**/*.html" 90 | ] 91 | } 92 | }, 93 | "test": { 94 | "builder": "@nrwl/jest:jest", 95 | "outputs": ["coverage/apps/calendar"], 96 | "options": { 97 | "jestConfig": "apps/calendar/jest.config.js", 98 | "passWithNoTests": true 99 | } 100 | } 101 | } 102 | }, 103 | "calendar-e2e": { 104 | "root": "apps/calendar-e2e", 105 | "sourceRoot": "apps/calendar-e2e/src", 106 | "projectType": "application", 107 | "architect": { 108 | "e2e": { 109 | "builder": "@nrwl/cypress:cypress", 110 | "options": { 111 | "cypressConfig": "apps/calendar-e2e/cypress.json", 112 | "tsConfig": "apps/calendar-e2e/tsconfig.e2e.json", 113 | "devServerTarget": "calendar:serve:development" 114 | }, 115 | "configurations": { 116 | "production": { 117 | "devServerTarget": "calendar:serve:production" 118 | } 119 | } 120 | }, 121 | "lint": { 122 | "builder": "@nrwl/linter:eslint", 123 | "options": { 124 | "lintFilePatterns": ["apps/calendar-e2e/**/*.{js,ts}"] 125 | } 126 | } 127 | } 128 | }, 129 | "mailbox": { 130 | "projectType": "application", 131 | "root": "apps/mailbox", 132 | "sourceRoot": "apps/mailbox/src", 133 | "prefix": "mfes", 134 | "architect": { 135 | "build": { 136 | "builder": "@angular-builders/custom-webpack:browser", 137 | "outputs": ["{options.outputPath}"], 138 | "options": { 139 | "outputPath": "dist/apps/mailbox", 140 | "index": "apps/mailbox/src/index.html", 141 | "main": "apps/mailbox/src/main.ts", 142 | "polyfills": "apps/mailbox/src/polyfills.ts", 143 | "tsConfig": "apps/mailbox/tsconfig.app.json", 144 | "inlineStyleLanguage": "scss", 145 | "assets": [ 146 | "apps/mailbox/src/favicon.ico", 147 | "apps/mailbox/src/assets" 148 | ], 149 | "styles": ["apps/mailbox/src/styles.scss"], 150 | "scripts": [] 151 | }, 152 | "configurations": { 153 | "production": { 154 | "budgets": [ 155 | { 156 | "type": "initial", 157 | "maximumWarning": "500kb", 158 | "maximumError": "1mb" 159 | }, 160 | { 161 | "type": "anyComponentStyle", 162 | "maximumWarning": "2kb", 163 | "maximumError": "4kb" 164 | } 165 | ], 166 | "fileReplacements": [ 167 | { 168 | "replace": "apps/mailbox/src/environments/environment.ts", 169 | "with": "apps/mailbox/src/environments/environment.prod.ts" 170 | } 171 | ], 172 | "outputHashing": "all", 173 | "customWebpackConfig": { 174 | "path": "apps/mailbox/webpack.prod.config.js" 175 | } 176 | }, 177 | "development": { 178 | "buildOptimizer": false, 179 | "optimization": false, 180 | "vendorChunk": true, 181 | "extractLicenses": false, 182 | "sourceMap": true, 183 | "namedChunks": true, 184 | "customWebpackConfig": { 185 | "path": "apps/mailbox/webpack.config.js" 186 | } 187 | } 188 | }, 189 | "defaultConfiguration": "production" 190 | }, 191 | "serve": { 192 | "builder": "@angular-builders/custom-webpack:dev-server", 193 | "configurations": { 194 | "production": { 195 | "browserTarget": "mailbox:build:production" 196 | }, 197 | "development": { 198 | "browserTarget": "mailbox:build:development" 199 | } 200 | }, 201 | "defaultConfiguration": "development" 202 | }, 203 | "extract-i18n": { 204 | "builder": "@angular-builders/custom-webpack:extract-i18n", 205 | "options": { 206 | "browserTarget": "mailbox:build" 207 | } 208 | }, 209 | "lint": { 210 | "builder": "@nrwl/linter:eslint", 211 | "options": { 212 | "lintFilePatterns": [ 213 | "apps/mailbox/src/**/*.ts", 214 | "apps/mailbox/src/**/*.html" 215 | ] 216 | } 217 | }, 218 | "test": { 219 | "builder": "@nrwl/jest:jest", 220 | "outputs": ["coverage/apps/mailbox"], 221 | "options": { 222 | "jestConfig": "apps/mailbox/jest.config.js", 223 | "passWithNoTests": true 224 | } 225 | } 226 | } 227 | }, 228 | "mailbox-e2e": { 229 | "root": "apps/mailbox-e2e", 230 | "sourceRoot": "apps/mailbox-e2e/src", 231 | "projectType": "application", 232 | "architect": { 233 | "e2e": { 234 | "builder": "@nrwl/cypress:cypress", 235 | "options": { 236 | "cypressConfig": "apps/mailbox-e2e/cypress.json", 237 | "tsConfig": "apps/mailbox-e2e/tsconfig.e2e.json", 238 | "devServerTarget": "mailbox:serve:development" 239 | }, 240 | "configurations": { 241 | "production": { 242 | "devServerTarget": "mailbox:serve:production" 243 | } 244 | } 245 | }, 246 | "lint": { 247 | "builder": "@nrwl/linter:eslint", 248 | "options": { 249 | "lintFilePatterns": ["apps/mailbox-e2e/**/*.{js,ts}"] 250 | } 251 | } 252 | } 253 | }, 254 | "shell": { 255 | "projectType": "application", 256 | "root": "apps/shell", 257 | "sourceRoot": "apps/shell/src", 258 | "prefix": "mfes", 259 | "architect": { 260 | "build": { 261 | "builder": "@angular-builders/custom-webpack:browser", 262 | "outputs": ["{options.outputPath}"], 263 | "options": { 264 | "outputPath": "dist/apps/shell", 265 | "index": "apps/shell/src/index.html", 266 | "main": "apps/shell/src/main.ts", 267 | "polyfills": "apps/shell/src/polyfills.ts", 268 | "tsConfig": "apps/shell/tsconfig.app.json", 269 | "inlineStyleLanguage": "scss", 270 | "assets": ["apps/shell/src/favicon.ico", "apps/shell/src/assets"], 271 | "styles": ["apps/shell/src/styles.scss"], 272 | "scripts": [] 273 | }, 274 | "configurations": { 275 | "production": { 276 | "budgets": [ 277 | { 278 | "type": "initial", 279 | "maximumWarning": "500kb", 280 | "maximumError": "1mb" 281 | }, 282 | { 283 | "type": "anyComponentStyle", 284 | "maximumWarning": "2kb", 285 | "maximumError": "4kb" 286 | } 287 | ], 288 | "fileReplacements": [ 289 | { 290 | "replace": "apps/shell/src/environments/environment.ts", 291 | "with": "apps/shell/src/environments/environment.prod.ts" 292 | } 293 | ], 294 | "outputHashing": "all", 295 | "customWebpackConfig": { 296 | "path": "apps/shell/webpack.prod.config.js" 297 | } 298 | }, 299 | "development": { 300 | "buildOptimizer": false, 301 | "optimization": false, 302 | "vendorChunk": true, 303 | "extractLicenses": false, 304 | "sourceMap": true, 305 | "namedChunks": true, 306 | "customWebpackConfig": { 307 | "path": "apps/shell/webpack.config.js" 308 | } 309 | } 310 | }, 311 | "defaultConfiguration": "production" 312 | }, 313 | "serve": { 314 | "builder": "@angular-builders/custom-webpack:dev-server", 315 | "configurations": { 316 | "production": { 317 | "browserTarget": "shell:build:production" 318 | }, 319 | "development": { 320 | "browserTarget": "shell:build:development" 321 | } 322 | }, 323 | "defaultConfiguration": "development" 324 | }, 325 | "extract-i18n": { 326 | "builder": "@angular-devkit/build-angular:extract-i18n", 327 | "options": { 328 | "browserTarget": "shell:build" 329 | } 330 | }, 331 | "lint": { 332 | "builder": "@nrwl/linter:eslint", 333 | "options": { 334 | "lintFilePatterns": [ 335 | "apps/shell/src/**/*.ts", 336 | "apps/shell/src/**/*.html" 337 | ] 338 | } 339 | }, 340 | "test": { 341 | "builder": "@nrwl/jest:jest", 342 | "outputs": ["coverage/apps/shell"], 343 | "options": { 344 | "jestConfig": "apps/shell/jest.config.js", 345 | "passWithNoTests": true 346 | } 347 | } 348 | } 349 | }, 350 | "shell-e2e": { 351 | "root": "apps/shell-e2e", 352 | "sourceRoot": "apps/shell-e2e/src", 353 | "projectType": "application", 354 | "architect": { 355 | "e2e": { 356 | "builder": "@nrwl/cypress:cypress", 357 | "options": { 358 | "cypressConfig": "apps/shell-e2e/cypress.json", 359 | "tsConfig": "apps/shell-e2e/tsconfig.e2e.json", 360 | "devServerTarget": "shell:serve:development" 361 | }, 362 | "configurations": { 363 | "production": { 364 | "devServerTarget": "shell:serve:production" 365 | } 366 | } 367 | }, 368 | "lint": { 369 | "builder": "@nrwl/linter:eslint", 370 | "options": { 371 | "lintFilePatterns": ["apps/shell-e2e/**/*.{js,ts}"] 372 | } 373 | } 374 | } 375 | } 376 | }, 377 | "cli": { 378 | "defaultCollection": "@nrwl/angular" 379 | }, 380 | "schematics": { 381 | "@nrwl/angular": { 382 | "application": { 383 | "linter": "eslint" 384 | }, 385 | "library": { 386 | "linter": "eslint" 387 | }, 388 | "storybook-configuration": { 389 | "linter": "eslint" 390 | } 391 | }, 392 | "@nrwl/angular:application": { 393 | "style": "scss", 394 | "linter": "eslint", 395 | "unitTestRunner": "jest", 396 | "e2eTestRunner": "cypress" 397 | }, 398 | "@nrwl/angular:library": { 399 | "style": "scss", 400 | "linter": "eslint", 401 | "unitTestRunner": "jest" 402 | }, 403 | "@nrwl/angular:component": { 404 | "style": "scss" 405 | } 406 | }, 407 | "defaultProject": "shell" 408 | } 409 | -------------------------------------------------------------------------------- /apps/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tieppt/nx-micro-frontends/62a0c5ab20489fc0d7bd50710fc6ae097418f137/apps/.gitkeep -------------------------------------------------------------------------------- /apps/calendar-e2e/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["plugin:cypress/recommended", "../../.eslintrc.json"], 3 | "ignorePatterns": ["!**/*"], 4 | "overrides": [ 5 | { 6 | "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], 7 | "rules": {} 8 | }, 9 | { 10 | "files": ["src/plugins/index.js"], 11 | "rules": { 12 | "@typescript-eslint/no-var-requires": "off", 13 | "no-undef": "off" 14 | } 15 | } 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /apps/calendar-e2e/cypress.json: -------------------------------------------------------------------------------- 1 | { 2 | "fileServerFolder": ".", 3 | "fixturesFolder": "./src/fixtures", 4 | "integrationFolder": "./src/integration", 5 | "modifyObstructiveCode": false, 6 | "pluginsFile": "./src/plugins/index", 7 | "supportFile": "./src/support/index.ts", 8 | "video": true, 9 | "videosFolder": "../../dist/cypress/apps/calendar-e2e/videos", 10 | "screenshotsFolder": "../../dist/cypress/apps/calendar-e2e/screenshots", 11 | "chromeWebSecurity": false 12 | } 13 | -------------------------------------------------------------------------------- /apps/calendar-e2e/src/fixtures/example.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Using fixtures to represent data", 3 | "email": "hello@cypress.io" 4 | } 5 | -------------------------------------------------------------------------------- /apps/calendar-e2e/src/integration/app.spec.ts: -------------------------------------------------------------------------------- 1 | import { getGreeting } from '../support/app.po'; 2 | 3 | describe('calendar', () => { 4 | beforeEach(() => cy.visit('/')); 5 | 6 | it('should display welcome message', () => { 7 | // Custom command example, see `../support/commands.ts` file 8 | cy.login('my-email@something.com', 'myPassword'); 9 | 10 | // Function helper example, see `../support/app.po.ts` file 11 | getGreeting().contains('Welcome to calendar!'); 12 | }); 13 | }); 14 | -------------------------------------------------------------------------------- /apps/calendar-e2e/src/plugins/index.js: -------------------------------------------------------------------------------- 1 | // *********************************************************** 2 | // This example plugins/index.js can be used to load plugins 3 | // 4 | // You can change the location of this file or turn off loading 5 | // the plugins file with the 'pluginsFile' configuration option. 6 | // 7 | // You can read more here: 8 | // https://on.cypress.io/plugins-guide 9 | // *********************************************************** 10 | 11 | // This function is called when a project is opened or re-opened (e.g. due to 12 | // the project's config changing) 13 | 14 | const { preprocessTypescript } = require('@nrwl/cypress/plugins/preprocessor'); 15 | 16 | module.exports = (on, config) => { 17 | // `on` is used to hook into various events Cypress emits 18 | // `config` is the resolved Cypress config 19 | 20 | // Preprocess Typescript file using Nx helper 21 | on('file:preprocessor', preprocessTypescript(config)); 22 | }; 23 | -------------------------------------------------------------------------------- /apps/calendar-e2e/src/support/app.po.ts: -------------------------------------------------------------------------------- 1 | export const getGreeting = () => cy.get('h1'); 2 | -------------------------------------------------------------------------------- /apps/calendar-e2e/src/support/commands.ts: -------------------------------------------------------------------------------- 1 | // *********************************************** 2 | // This example commands.js shows you how to 3 | // create various custom commands and overwrite 4 | // existing commands. 5 | // 6 | // For more comprehensive examples of custom 7 | // commands please read more here: 8 | // https://on.cypress.io/custom-commands 9 | // *********************************************** 10 | 11 | // eslint-disable-next-line @typescript-eslint/no-namespace 12 | declare namespace Cypress { 13 | // eslint-disable-next-line @typescript-eslint/no-unused-vars 14 | interface Chainable { 15 | login(email: string, password: string): void; 16 | } 17 | } 18 | // 19 | // -- This is a parent command -- 20 | Cypress.Commands.add('login', (email, password) => { 21 | console.log('Custom command example: Login', email, password); 22 | }); 23 | // 24 | // -- This is a child command -- 25 | // Cypress.Commands.add("drag", { prevSubject: 'element'}, (subject, options) => { ... }) 26 | // 27 | // 28 | // -- This is a dual command -- 29 | // Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... }) 30 | // 31 | // 32 | // -- This will overwrite an existing command -- 33 | // Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... }) 34 | -------------------------------------------------------------------------------- /apps/calendar-e2e/src/support/index.ts: -------------------------------------------------------------------------------- 1 | // *********************************************************** 2 | // This example support/index.js is processed and 3 | // loaded automatically before your test files. 4 | // 5 | // This is a great place to put global configuration and 6 | // behavior that modifies Cypress. 7 | // 8 | // You can change the location of this file or turn off 9 | // automatically serving support files with the 10 | // 'supportFile' configuration option. 11 | // 12 | // You can read more here: 13 | // https://on.cypress.io/configuration 14 | // *********************************************************** 15 | 16 | // Import commands.js using ES2015 syntax: 17 | import './commands'; 18 | -------------------------------------------------------------------------------- /apps/calendar-e2e/tsconfig.e2e.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "sourceMap": false, 5 | "outDir": "../../dist/out-tsc", 6 | "allowJs": true, 7 | "types": ["cypress", "node"], 8 | "forceConsistentCasingInFileNames": true, 9 | "strict": true, 10 | "noImplicitReturns": true, 11 | "noFallthroughCasesInSwitch": true 12 | }, 13 | "include": ["src/**/*.ts", "src/**/*.js"], 14 | "angularCompilerOptions": { 15 | "strictInjectionParameters": true, 16 | "strictInputAccessModifiers": true, 17 | "strictTemplates": true 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /apps/calendar-e2e/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base.json", 3 | "files": [], 4 | "include": [], 5 | "references": [ 6 | { 7 | "path": "./tsconfig.e2e.json" 8 | } 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /apps/calendar/.browserslistrc: -------------------------------------------------------------------------------- 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 | # For the full list of supported browsers by the Angular framework, please see: 6 | # https://angular.io/guide/browser-support 7 | 8 | # You can see what browsers were selected by your queries by running: 9 | # npx browserslist 10 | 11 | last 1 Chrome version 12 | last 1 Firefox version 13 | last 2 Edge major versions 14 | last 2 Safari major versions 15 | last 2 iOS major versions 16 | Firefox ESR 17 | not IE 11 # Angular supports IE 11 only as an opt-in. To opt-in, remove the 'not' prefix on this line. 18 | -------------------------------------------------------------------------------- /apps/calendar/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["../../.eslintrc.json"], 3 | "ignorePatterns": ["!**/*"], 4 | "overrides": [ 5 | { 6 | "files": ["*.ts"], 7 | "extends": [ 8 | "plugin:@nrwl/nx/angular", 9 | "plugin:@angular-eslint/template/process-inline-templates" 10 | ], 11 | "rules": { 12 | "@angular-eslint/directive-selector": [ 13 | "error", 14 | { 15 | "type": "attribute", 16 | "prefix": "mfes", 17 | "style": "camelCase" 18 | } 19 | ], 20 | "@angular-eslint/component-selector": [ 21 | "error", 22 | { 23 | "type": "element", 24 | "prefix": "mfes", 25 | "style": "kebab-case" 26 | } 27 | ] 28 | } 29 | }, 30 | { 31 | "files": ["*.html"], 32 | "extends": ["plugin:@nrwl/nx/angular-template"], 33 | "rules": {} 34 | } 35 | ] 36 | } 37 | -------------------------------------------------------------------------------- /apps/calendar/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | displayName: 'calendar', 3 | preset: '../../jest.preset.js', 4 | setupFilesAfterEnv: ['/src/test-setup.ts'], 5 | globals: { 6 | 'ts-jest': { 7 | tsconfig: '/tsconfig.spec.json', 8 | stringifyContentPathRegex: '\\.(html|svg)$', 9 | }, 10 | }, 11 | coverageDirectory: '../../coverage/apps/calendar', 12 | transform: { 13 | '^.+\\.(ts|js|html)$': 'jest-preset-angular', 14 | }, 15 | snapshotSerializers: [ 16 | 'jest-preset-angular/build/serializers/no-ng-attributes', 17 | 'jest-preset-angular/build/serializers/ng-snapshot', 18 | 'jest-preset-angular/build/serializers/html-comment', 19 | ], 20 | }; 21 | -------------------------------------------------------------------------------- /apps/calendar/src/app/app.component.html: -------------------------------------------------------------------------------- 1 |
2 |

Welcome to {{ title }}!

3 |
4 |
5 | 6 |
7 | -------------------------------------------------------------------------------- /apps/calendar/src/app/app.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tieppt/nx-micro-frontends/62a0c5ab20489fc0d7bd50710fc6ae097418f137/apps/calendar/src/app/app.component.scss -------------------------------------------------------------------------------- /apps/calendar/src/app/app.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed } from '@angular/core/testing'; 2 | import { AppComponent } from './app.component'; 3 | import { RouterTestingModule } from '@angular/router/testing'; 4 | 5 | describe('AppComponent', () => { 6 | beforeEach(async () => { 7 | await TestBed.configureTestingModule({ 8 | imports: [RouterTestingModule], 9 | declarations: [AppComponent], 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 'calendar'`, () => { 20 | const fixture = TestBed.createComponent(AppComponent); 21 | const app = fixture.componentInstance; 22 | expect(app.title).toEqual('calendar'); 23 | }); 24 | 25 | it('should render title', () => { 26 | const fixture = TestBed.createComponent(AppComponent); 27 | fixture.detectChanges(); 28 | const compiled = fixture.nativeElement as HTMLElement; 29 | expect(compiled.querySelector('h1')?.textContent).toContain( 30 | 'Welcome to calendar!' 31 | ); 32 | }); 33 | }); 34 | -------------------------------------------------------------------------------- /apps/calendar/src/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'mfes-root', 5 | templateUrl: './app.component.html', 6 | styleUrls: ['./app.component.scss'], 7 | }) 8 | export class AppComponent { 9 | title = 'calendar'; 10 | } 11 | -------------------------------------------------------------------------------- /apps/calendar/src/app/app.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { BrowserModule } from '@angular/platform-browser'; 3 | 4 | import { AppComponent } from './app.component'; 5 | import { RouterModule } from '@angular/router'; 6 | 7 | @NgModule({ 8 | declarations: [AppComponent], 9 | imports: [ 10 | BrowserModule, 11 | RouterModule.forRoot([ 12 | { 13 | path: '', 14 | pathMatch: 'full', 15 | redirectTo: '/calendar' 16 | }, 17 | { 18 | path: 'calendar', 19 | loadChildren: () => import('./calendar/calendar.module').then(m => m.CalendarModule), 20 | } 21 | ], { initialNavigation: 'enabledBlocking' }), 22 | ], 23 | providers: [], 24 | bootstrap: [AppComponent], 25 | }) 26 | export class AppModule {} 27 | -------------------------------------------------------------------------------- /apps/calendar/src/app/calendar/calendar.component.css: -------------------------------------------------------------------------------- 1 | :host { 2 | display: flex; 3 | border: 5px dashed green; 4 | } -------------------------------------------------------------------------------- /apps/calendar/src/app/calendar/calendar.component.html: -------------------------------------------------------------------------------- 1 |

calendar works!

2 | -------------------------------------------------------------------------------- /apps/calendar/src/app/calendar/calendar.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { CalendarComponent } from './calendar.component'; 4 | 5 | describe('CalendarComponent', () => { 6 | let component: CalendarComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ CalendarComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(CalendarComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /apps/calendar/src/app/calendar/calendar.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'mfes-calendar', 5 | templateUrl: './calendar.component.html', 6 | styleUrls: ['./calendar.component.css'] 7 | }) 8 | export class CalendarComponent implements OnInit { 9 | 10 | constructor() { } 11 | 12 | ngOnInit(): void { 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /apps/calendar/src/app/calendar/calendar.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | import { CalendarComponent } from './calendar.component'; 4 | import { RouterModule } from '@angular/router'; 5 | 6 | @NgModule({ 7 | declarations: [ 8 | CalendarComponent 9 | ], 10 | imports: [ 11 | CommonModule, 12 | RouterModule.forChild([ 13 | { 14 | path: '', 15 | pathMatch: 'full', 16 | component: CalendarComponent 17 | } 18 | ]) 19 | ] 20 | }) 21 | export class CalendarModule { } 22 | -------------------------------------------------------------------------------- /apps/calendar/src/assets/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tieppt/nx-micro-frontends/62a0c5ab20489fc0d7bd50710fc6ae097418f137/apps/calendar/src/assets/.gitkeep -------------------------------------------------------------------------------- /apps/calendar/src/bootstrap.ts: -------------------------------------------------------------------------------- 1 | import { enableProdMode } from '@angular/core'; 2 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 3 | 4 | import { AppModule } from './app/app.module'; 5 | import { environment } from './environments/environment'; 6 | 7 | if (environment.production) { 8 | enableProdMode(); 9 | } 10 | 11 | platformBrowserDynamic() 12 | .bootstrapModule(AppModule) 13 | .catch((err) => console.error(err)); 14 | -------------------------------------------------------------------------------- /apps/calendar/src/environments/environment.prod.ts: -------------------------------------------------------------------------------- 1 | export const environment = { 2 | production: true, 3 | }; 4 | -------------------------------------------------------------------------------- /apps/calendar/src/environments/environment.ts: -------------------------------------------------------------------------------- 1 | // This file can be replaced during build by using the `fileReplacements` array. 2 | // `ng build` 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/plugins/zone-error'; // Included with Angular CLI. 17 | -------------------------------------------------------------------------------- /apps/calendar/src/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tieppt/nx-micro-frontends/62a0c5ab20489fc0d7bd50710fc6ae097418f137/apps/calendar/src/favicon.ico -------------------------------------------------------------------------------- /apps/calendar/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Calendar 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /apps/calendar/src/main.ts: -------------------------------------------------------------------------------- 1 | import('./bootstrap'); 2 | -------------------------------------------------------------------------------- /apps/calendar/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 | * IE11 requires the following for NgClass support on SVG elements 23 | */ 24 | // import 'classlist.js'; // Run `npm install --save classlist.js`. 25 | 26 | /** 27 | * Web Animations `@angular/platform-browser/animations` 28 | * Only required if AnimationBuilder is used within the application and using IE/Edge or Safari. 29 | * Standard animation support in Angular DOES NOT require any polyfills (as of Angular 6.0). 30 | */ 31 | // import 'web-animations-js'; // Run `npm install --save web-animations-js`. 32 | 33 | /** 34 | * By default, zone.js will patch all possible macroTask and DomEvents 35 | * user can disable parts of macroTask/DomEvents patch by setting following flags 36 | * because those flags need to be set before `zone.js` being loaded, and webpack 37 | * will put import in the top of bundle, so user need to create a separate file 38 | * in this directory (for example: zone-flags.ts), and put the following flags 39 | * into that file, and then add the following code before importing zone.js. 40 | * import './zone-flags'; 41 | * 42 | * The flags allowed in zone-flags.ts are listed here. 43 | * 44 | * The following flags will work for all browsers. 45 | * 46 | * (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame 47 | * (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick 48 | * (window as any).__zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames 49 | * 50 | * in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js 51 | * with the following flag, it will bypass `zone.js` patch for IE/Edge 52 | * 53 | * (window as any).__Zone_enable_cross_context_check = true; 54 | * 55 | */ 56 | 57 | /*************************************************************************************************** 58 | * Zone JS is required by default for Angular itself. 59 | */ 60 | import 'zone.js'; // Included with Angular CLI. 61 | 62 | /*************************************************************************************************** 63 | * APPLICATION IMPORTS 64 | */ 65 | -------------------------------------------------------------------------------- /apps/calendar/src/styles.scss: -------------------------------------------------------------------------------- 1 | /* You can add global styles to this file, and also import other style files */ 2 | html, 3 | body { 4 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; 5 | } -------------------------------------------------------------------------------- /apps/calendar/src/test-setup.ts: -------------------------------------------------------------------------------- 1 | import 'jest-preset-angular/setup-jest'; 2 | -------------------------------------------------------------------------------- /apps/calendar/tsconfig.app.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "types": [] 6 | }, 7 | "files": ["src/main.ts", "src/polyfills.ts"], 8 | "include": ["src/**/*.d.ts"] 9 | } 10 | -------------------------------------------------------------------------------- /apps/calendar/tsconfig.editor.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "include": ["**/*.ts"], 4 | "compilerOptions": { 5 | "types": ["jest", "node"] 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /apps/calendar/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base.json", 3 | "files": [], 4 | "include": [], 5 | "references": [ 6 | { 7 | "path": "./tsconfig.app.json" 8 | }, 9 | { 10 | "path": "./tsconfig.spec.json" 11 | }, 12 | { 13 | "path": "./tsconfig.editor.json" 14 | } 15 | ], 16 | "compilerOptions": { 17 | "forceConsistentCasingInFileNames": true, 18 | "strict": true, 19 | "noImplicitReturns": true, 20 | "noFallthroughCasesInSwitch": true 21 | }, 22 | "angularCompilerOptions": { 23 | "strictInjectionParameters": true, 24 | "strictInputAccessModifiers": true, 25 | "strictTemplates": true 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /apps/calendar/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "module": "commonjs", 6 | "types": ["jest", "node"] 7 | }, 8 | "files": ["src/test-setup.ts"], 9 | "include": ["**/*.spec.ts", "**/*.d.ts"] 10 | } 11 | -------------------------------------------------------------------------------- /apps/calendar/webpack.config.js: -------------------------------------------------------------------------------- 1 | const { ModuleFederationPlugin } = require('webpack').container; 2 | 3 | module.exports = { 4 | output: { 5 | publicPath: "http://localhost:5400/", 6 | uniqueName: "calendar" 7 | }, 8 | optimization: { 9 | runtimeChunk: false 10 | }, 11 | plugins: [ 12 | new ModuleFederationPlugin({ 13 | name: "calendar", 14 | library: { type: "var", name: "calendar" }, 15 | filename: "remoteEntry.js", 16 | exposes: { 17 | './CalendarModule': './apps/calendar/src/app/calendar/calendar.module.ts', 18 | }, 19 | shared: ["@angular/core", "@angular/common", "@angular/router"] 20 | }) 21 | ], 22 | }; 23 | -------------------------------------------------------------------------------- /apps/calendar/webpack.prod.config.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./webpack.config'); 2 | -------------------------------------------------------------------------------- /apps/mailbox-e2e/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["plugin:cypress/recommended", "../../.eslintrc.json"], 3 | "ignorePatterns": ["!**/*"], 4 | "overrides": [ 5 | { 6 | "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], 7 | "rules": {} 8 | }, 9 | { 10 | "files": ["src/plugins/index.js"], 11 | "rules": { 12 | "@typescript-eslint/no-var-requires": "off", 13 | "no-undef": "off" 14 | } 15 | } 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /apps/mailbox-e2e/cypress.json: -------------------------------------------------------------------------------- 1 | { 2 | "fileServerFolder": ".", 3 | "fixturesFolder": "./src/fixtures", 4 | "integrationFolder": "./src/integration", 5 | "modifyObstructiveCode": false, 6 | "pluginsFile": "./src/plugins/index", 7 | "supportFile": "./src/support/index.ts", 8 | "video": true, 9 | "videosFolder": "../../dist/cypress/apps/mailbox-e2e/videos", 10 | "screenshotsFolder": "../../dist/cypress/apps/mailbox-e2e/screenshots", 11 | "chromeWebSecurity": false 12 | } 13 | -------------------------------------------------------------------------------- /apps/mailbox-e2e/src/fixtures/example.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Using fixtures to represent data", 3 | "email": "hello@cypress.io" 4 | } 5 | -------------------------------------------------------------------------------- /apps/mailbox-e2e/src/integration/app.spec.ts: -------------------------------------------------------------------------------- 1 | import { getGreeting } from '../support/app.po'; 2 | 3 | describe('mailbox', () => { 4 | beforeEach(() => cy.visit('/')); 5 | 6 | it('should display welcome message', () => { 7 | // Custom command example, see `../support/commands.ts` file 8 | cy.login('my-email@something.com', 'myPassword'); 9 | 10 | // Function helper example, see `../support/app.po.ts` file 11 | getGreeting().contains('Welcome to mailbox!'); 12 | }); 13 | }); 14 | -------------------------------------------------------------------------------- /apps/mailbox-e2e/src/plugins/index.js: -------------------------------------------------------------------------------- 1 | // *********************************************************** 2 | // This example plugins/index.js can be used to load plugins 3 | // 4 | // You can change the location of this file or turn off loading 5 | // the plugins file with the 'pluginsFile' configuration option. 6 | // 7 | // You can read more here: 8 | // https://on.cypress.io/plugins-guide 9 | // *********************************************************** 10 | 11 | // This function is called when a project is opened or re-opened (e.g. due to 12 | // the project's config changing) 13 | 14 | const { preprocessTypescript } = require('@nrwl/cypress/plugins/preprocessor'); 15 | 16 | module.exports = (on, config) => { 17 | // `on` is used to hook into various events Cypress emits 18 | // `config` is the resolved Cypress config 19 | 20 | // Preprocess Typescript file using Nx helper 21 | on('file:preprocessor', preprocessTypescript(config)); 22 | }; 23 | -------------------------------------------------------------------------------- /apps/mailbox-e2e/src/support/app.po.ts: -------------------------------------------------------------------------------- 1 | export const getGreeting = () => cy.get('h1'); 2 | -------------------------------------------------------------------------------- /apps/mailbox-e2e/src/support/commands.ts: -------------------------------------------------------------------------------- 1 | // *********************************************** 2 | // This example commands.js shows you how to 3 | // create various custom commands and overwrite 4 | // existing commands. 5 | // 6 | // For more comprehensive examples of custom 7 | // commands please read more here: 8 | // https://on.cypress.io/custom-commands 9 | // *********************************************** 10 | 11 | // eslint-disable-next-line @typescript-eslint/no-namespace 12 | declare namespace Cypress { 13 | // eslint-disable-next-line @typescript-eslint/no-unused-vars 14 | interface Chainable { 15 | login(email: string, password: string): void; 16 | } 17 | } 18 | // 19 | // -- This is a parent command -- 20 | Cypress.Commands.add('login', (email, password) => { 21 | console.log('Custom command example: Login', email, password); 22 | }); 23 | // 24 | // -- This is a child command -- 25 | // Cypress.Commands.add("drag", { prevSubject: 'element'}, (subject, options) => { ... }) 26 | // 27 | // 28 | // -- This is a dual command -- 29 | // Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... }) 30 | // 31 | // 32 | // -- This will overwrite an existing command -- 33 | // Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... }) 34 | -------------------------------------------------------------------------------- /apps/mailbox-e2e/src/support/index.ts: -------------------------------------------------------------------------------- 1 | // *********************************************************** 2 | // This example support/index.js is processed and 3 | // loaded automatically before your test files. 4 | // 5 | // This is a great place to put global configuration and 6 | // behavior that modifies Cypress. 7 | // 8 | // You can change the location of this file or turn off 9 | // automatically serving support files with the 10 | // 'supportFile' configuration option. 11 | // 12 | // You can read more here: 13 | // https://on.cypress.io/configuration 14 | // *********************************************************** 15 | 16 | // Import commands.js using ES2015 syntax: 17 | import './commands'; 18 | -------------------------------------------------------------------------------- /apps/mailbox-e2e/tsconfig.e2e.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "sourceMap": false, 5 | "outDir": "../../dist/out-tsc", 6 | "allowJs": true, 7 | "types": ["cypress", "node"], 8 | "forceConsistentCasingInFileNames": true, 9 | "strict": true, 10 | "noImplicitReturns": true, 11 | "noFallthroughCasesInSwitch": true 12 | }, 13 | "include": ["src/**/*.ts", "src/**/*.js"], 14 | "angularCompilerOptions": { 15 | "strictInjectionParameters": true, 16 | "strictInputAccessModifiers": true, 17 | "strictTemplates": true 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /apps/mailbox-e2e/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base.json", 3 | "files": [], 4 | "include": [], 5 | "references": [ 6 | { 7 | "path": "./tsconfig.e2e.json" 8 | } 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /apps/mailbox/.browserslistrc: -------------------------------------------------------------------------------- 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 | # For the full list of supported browsers by the Angular framework, please see: 6 | # https://angular.io/guide/browser-support 7 | 8 | # You can see what browsers were selected by your queries by running: 9 | # npx browserslist 10 | 11 | last 1 Chrome version 12 | last 1 Firefox version 13 | last 2 Edge major versions 14 | last 2 Safari major versions 15 | last 2 iOS major versions 16 | Firefox ESR 17 | not IE 11 # Angular supports IE 11 only as an opt-in. To opt-in, remove the 'not' prefix on this line. 18 | -------------------------------------------------------------------------------- /apps/mailbox/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["../../.eslintrc.json"], 3 | "ignorePatterns": ["!**/*"], 4 | "overrides": [ 5 | { 6 | "files": ["*.ts"], 7 | "extends": [ 8 | "plugin:@nrwl/nx/angular", 9 | "plugin:@angular-eslint/template/process-inline-templates" 10 | ], 11 | "rules": { 12 | "@angular-eslint/directive-selector": [ 13 | "error", 14 | { 15 | "type": "attribute", 16 | "prefix": "mfes", 17 | "style": "camelCase" 18 | } 19 | ], 20 | "@angular-eslint/component-selector": [ 21 | "error", 22 | { 23 | "type": "element", 24 | "prefix": "mfes", 25 | "style": "kebab-case" 26 | } 27 | ] 28 | } 29 | }, 30 | { 31 | "files": ["*.html"], 32 | "extends": ["plugin:@nrwl/nx/angular-template"], 33 | "rules": {} 34 | } 35 | ] 36 | } 37 | -------------------------------------------------------------------------------- /apps/mailbox/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | displayName: 'mailbox', 3 | preset: '../../jest.preset.js', 4 | setupFilesAfterEnv: ['/src/test-setup.ts'], 5 | globals: { 6 | 'ts-jest': { 7 | tsconfig: '/tsconfig.spec.json', 8 | stringifyContentPathRegex: '\\.(html|svg)$', 9 | }, 10 | }, 11 | coverageDirectory: '../../coverage/apps/mailbox', 12 | transform: { 13 | '^.+\\.(ts|js|html)$': 'jest-preset-angular', 14 | }, 15 | snapshotSerializers: [ 16 | 'jest-preset-angular/build/serializers/no-ng-attributes', 17 | 'jest-preset-angular/build/serializers/ng-snapshot', 18 | 'jest-preset-angular/build/serializers/html-comment', 19 | ], 20 | }; 21 | -------------------------------------------------------------------------------- /apps/mailbox/src/app/app.component.html: -------------------------------------------------------------------------------- 1 |
2 |

Welcome to {{ title }}!

3 |
4 |
5 | 6 |
7 | -------------------------------------------------------------------------------- /apps/mailbox/src/app/app.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tieppt/nx-micro-frontends/62a0c5ab20489fc0d7bd50710fc6ae097418f137/apps/mailbox/src/app/app.component.scss -------------------------------------------------------------------------------- /apps/mailbox/src/app/app.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed } from '@angular/core/testing'; 2 | import { AppComponent } from './app.component'; 3 | import { RouterTestingModule } from '@angular/router/testing'; 4 | 5 | describe('AppComponent', () => { 6 | beforeEach(async () => { 7 | await TestBed.configureTestingModule({ 8 | imports: [RouterTestingModule], 9 | declarations: [AppComponent], 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 'mailbox'`, () => { 20 | const fixture = TestBed.createComponent(AppComponent); 21 | const app = fixture.componentInstance; 22 | expect(app.title).toEqual('mailbox'); 23 | }); 24 | 25 | it('should render title', () => { 26 | const fixture = TestBed.createComponent(AppComponent); 27 | fixture.detectChanges(); 28 | const compiled = fixture.nativeElement as HTMLElement; 29 | expect(compiled.querySelector('h1')?.textContent).toContain( 30 | 'Welcome to mailbox!' 31 | ); 32 | }); 33 | }); 34 | -------------------------------------------------------------------------------- /apps/mailbox/src/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'mfes-root', 5 | templateUrl: './app.component.html', 6 | styleUrls: ['./app.component.scss'], 7 | }) 8 | export class AppComponent { 9 | title = 'mailbox'; 10 | } 11 | -------------------------------------------------------------------------------- /apps/mailbox/src/app/app.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { BrowserModule } from '@angular/platform-browser'; 3 | 4 | import { AppComponent } from './app.component'; 5 | import { RouterModule } from '@angular/router'; 6 | 7 | @NgModule({ 8 | declarations: [AppComponent], 9 | imports: [ 10 | BrowserModule, 11 | RouterModule.forRoot([ 12 | { 13 | path: '', 14 | pathMatch: 'full', 15 | redirectTo: '/mailbox' 16 | }, 17 | { 18 | path: 'mailbox', 19 | loadChildren: () => import('./mailbox/mailbox.module').then(m => m.MailboxModule) 20 | } 21 | ], { initialNavigation: 'enabledBlocking' }), 22 | ], 23 | providers: [], 24 | bootstrap: [AppComponent], 25 | }) 26 | export class AppModule {} 27 | -------------------------------------------------------------------------------- /apps/mailbox/src/app/mailbox/mailbox-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { RouterModule, Routes } from '@angular/router'; 3 | import { MailboxComponent } from './mailbox.component'; 4 | 5 | const routes: Routes = [ 6 | { 7 | path: '', 8 | pathMatch: 'full', 9 | component: MailboxComponent 10 | } 11 | ]; 12 | 13 | @NgModule({ 14 | imports: [RouterModule.forChild(routes)], 15 | exports: [RouterModule] 16 | }) 17 | export class MailboxRoutingModule { } 18 | -------------------------------------------------------------------------------- /apps/mailbox/src/app/mailbox/mailbox.component.css: -------------------------------------------------------------------------------- 1 | :host { 2 | display: flex; 3 | border: 5px dashed palevioletred; 4 | } -------------------------------------------------------------------------------- /apps/mailbox/src/app/mailbox/mailbox.component.html: -------------------------------------------------------------------------------- 1 |

mailbox works!

2 | -------------------------------------------------------------------------------- /apps/mailbox/src/app/mailbox/mailbox.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { MailboxComponent } from './mailbox.component'; 4 | 5 | describe('MailboxComponent', () => { 6 | let component: MailboxComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ MailboxComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(MailboxComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /apps/mailbox/src/app/mailbox/mailbox.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'mfes-mailbox', 5 | templateUrl: './mailbox.component.html', 6 | styleUrls: ['./mailbox.component.css'] 7 | }) 8 | export class MailboxComponent implements OnInit { 9 | 10 | constructor() { } 11 | 12 | ngOnInit(): void { 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /apps/mailbox/src/app/mailbox/mailbox.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | 4 | import { MailboxRoutingModule } from './mailbox-routing.module'; 5 | import { MailboxComponent } from './mailbox.component'; 6 | 7 | 8 | @NgModule({ 9 | declarations: [ 10 | MailboxComponent 11 | ], 12 | imports: [ 13 | CommonModule, 14 | MailboxRoutingModule 15 | ] 16 | }) 17 | export class MailboxModule { } 18 | -------------------------------------------------------------------------------- /apps/mailbox/src/assets/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tieppt/nx-micro-frontends/62a0c5ab20489fc0d7bd50710fc6ae097418f137/apps/mailbox/src/assets/.gitkeep -------------------------------------------------------------------------------- /apps/mailbox/src/bootstrap.ts: -------------------------------------------------------------------------------- 1 | import { enableProdMode } from '@angular/core'; 2 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 3 | 4 | import { AppModule } from './app/app.module'; 5 | import { environment } from './environments/environment'; 6 | 7 | if (environment.production) { 8 | enableProdMode(); 9 | } 10 | 11 | platformBrowserDynamic() 12 | .bootstrapModule(AppModule) 13 | .catch((err) => console.error(err)); 14 | -------------------------------------------------------------------------------- /apps/mailbox/src/environments/environment.prod.ts: -------------------------------------------------------------------------------- 1 | export const environment = { 2 | production: true, 3 | }; 4 | -------------------------------------------------------------------------------- /apps/mailbox/src/environments/environment.ts: -------------------------------------------------------------------------------- 1 | // This file can be replaced during build by using the `fileReplacements` array. 2 | // `ng build` 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/plugins/zone-error'; // Included with Angular CLI. 17 | -------------------------------------------------------------------------------- /apps/mailbox/src/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tieppt/nx-micro-frontends/62a0c5ab20489fc0d7bd50710fc6ae097418f137/apps/mailbox/src/favicon.ico -------------------------------------------------------------------------------- /apps/mailbox/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Mailbox 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /apps/mailbox/src/main.ts: -------------------------------------------------------------------------------- 1 | import('./bootstrap'); 2 | -------------------------------------------------------------------------------- /apps/mailbox/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 | * IE11 requires the following for NgClass support on SVG elements 23 | */ 24 | // import 'classlist.js'; // Run `npm install --save classlist.js`. 25 | 26 | /** 27 | * Web Animations `@angular/platform-browser/animations` 28 | * Only required if AnimationBuilder is used within the application and using IE/Edge or Safari. 29 | * Standard animation support in Angular DOES NOT require any polyfills (as of Angular 6.0). 30 | */ 31 | // import 'web-animations-js'; // Run `npm install --save web-animations-js`. 32 | 33 | /** 34 | * By default, zone.js will patch all possible macroTask and DomEvents 35 | * user can disable parts of macroTask/DomEvents patch by setting following flags 36 | * because those flags need to be set before `zone.js` being loaded, and webpack 37 | * will put import in the top of bundle, so user need to create a separate file 38 | * in this directory (for example: zone-flags.ts), and put the following flags 39 | * into that file, and then add the following code before importing zone.js. 40 | * import './zone-flags'; 41 | * 42 | * The flags allowed in zone-flags.ts are listed here. 43 | * 44 | * The following flags will work for all browsers. 45 | * 46 | * (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame 47 | * (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick 48 | * (window as any).__zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames 49 | * 50 | * in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js 51 | * with the following flag, it will bypass `zone.js` patch for IE/Edge 52 | * 53 | * (window as any).__Zone_enable_cross_context_check = true; 54 | * 55 | */ 56 | 57 | /*************************************************************************************************** 58 | * Zone JS is required by default for Angular itself. 59 | */ 60 | import 'zone.js'; // Included with Angular CLI. 61 | 62 | /*************************************************************************************************** 63 | * APPLICATION IMPORTS 64 | */ 65 | -------------------------------------------------------------------------------- /apps/mailbox/src/styles.scss: -------------------------------------------------------------------------------- 1 | /* You can add global styles to this file, and also import other style files */ 2 | html, 3 | body { 4 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; 5 | } -------------------------------------------------------------------------------- /apps/mailbox/src/test-setup.ts: -------------------------------------------------------------------------------- 1 | import 'jest-preset-angular/setup-jest'; 2 | -------------------------------------------------------------------------------- /apps/mailbox/tsconfig.app.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "types": [] 6 | }, 7 | "files": ["src/main.ts", "src/polyfills.ts"], 8 | "include": ["src/**/*.d.ts"] 9 | } 10 | -------------------------------------------------------------------------------- /apps/mailbox/tsconfig.editor.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "include": ["**/*.ts"], 4 | "compilerOptions": { 5 | "types": ["jest", "node"] 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /apps/mailbox/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base.json", 3 | "files": [], 4 | "include": [], 5 | "references": [ 6 | { 7 | "path": "./tsconfig.app.json" 8 | }, 9 | { 10 | "path": "./tsconfig.spec.json" 11 | }, 12 | { 13 | "path": "./tsconfig.editor.json" 14 | } 15 | ], 16 | "compilerOptions": { 17 | "forceConsistentCasingInFileNames": true, 18 | "strict": true, 19 | "noImplicitReturns": true, 20 | "noFallthroughCasesInSwitch": true 21 | }, 22 | "angularCompilerOptions": { 23 | "strictInjectionParameters": true, 24 | "strictInputAccessModifiers": true, 25 | "strictTemplates": true 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /apps/mailbox/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "module": "commonjs", 6 | "types": ["jest", "node"] 7 | }, 8 | "files": ["src/test-setup.ts"], 9 | "include": ["**/*.spec.ts", "**/*.d.ts"] 10 | } 11 | -------------------------------------------------------------------------------- /apps/mailbox/webpack.config.js: -------------------------------------------------------------------------------- 1 | const { ModuleFederationPlugin } = require('webpack').container; 2 | 3 | module.exports = { 4 | output: { 5 | publicPath: "http://localhost:5300/", 6 | uniqueName: "mailbox" 7 | }, 8 | optimization: { 9 | runtimeChunk: false 10 | }, 11 | plugins: [ 12 | new ModuleFederationPlugin({ 13 | name: "mailbox", 14 | library: { type: "var", name: "mailbox" }, 15 | filename: "remoteEntry.js", 16 | exposes: { 17 | './MailboxModule': './apps/mailbox/src/app/mailbox/mailbox.module.ts', 18 | }, 19 | shared: ["@angular/core", "@angular/common", "@angular/router"] 20 | }) 21 | ], 22 | }; 23 | -------------------------------------------------------------------------------- /apps/mailbox/webpack.prod.config.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./webpack.config'); 2 | -------------------------------------------------------------------------------- /apps/shell-e2e/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["plugin:cypress/recommended", "../../.eslintrc.json"], 3 | "ignorePatterns": ["!**/*"], 4 | "overrides": [ 5 | { 6 | "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], 7 | "rules": {} 8 | }, 9 | { 10 | "files": ["src/plugins/index.js"], 11 | "rules": { 12 | "@typescript-eslint/no-var-requires": "off", 13 | "no-undef": "off" 14 | } 15 | } 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /apps/shell-e2e/cypress.json: -------------------------------------------------------------------------------- 1 | { 2 | "fileServerFolder": ".", 3 | "fixturesFolder": "./src/fixtures", 4 | "integrationFolder": "./src/integration", 5 | "modifyObstructiveCode": false, 6 | "pluginsFile": "./src/plugins/index", 7 | "supportFile": "./src/support/index.ts", 8 | "video": true, 9 | "videosFolder": "../../dist/cypress/apps/shell-e2e/videos", 10 | "screenshotsFolder": "../../dist/cypress/apps/shell-e2e/screenshots", 11 | "chromeWebSecurity": false 12 | } 13 | -------------------------------------------------------------------------------- /apps/shell-e2e/src/fixtures/example.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Using fixtures to represent data", 3 | "email": "hello@cypress.io" 4 | } 5 | -------------------------------------------------------------------------------- /apps/shell-e2e/src/integration/app.spec.ts: -------------------------------------------------------------------------------- 1 | import { getGreeting } from '../support/app.po'; 2 | 3 | describe('shell', () => { 4 | beforeEach(() => cy.visit('/')); 5 | 6 | it('should display welcome message', () => { 7 | // Custom command example, see `../support/commands.ts` file 8 | cy.login('my-email@something.com', 'myPassword'); 9 | 10 | // Function helper example, see `../support/app.po.ts` file 11 | getGreeting().contains('Welcome to shell!'); 12 | }); 13 | }); 14 | -------------------------------------------------------------------------------- /apps/shell-e2e/src/plugins/index.js: -------------------------------------------------------------------------------- 1 | // *********************************************************** 2 | // This example plugins/index.js can be used to load plugins 3 | // 4 | // You can change the location of this file or turn off loading 5 | // the plugins file with the 'pluginsFile' configuration option. 6 | // 7 | // You can read more here: 8 | // https://on.cypress.io/plugins-guide 9 | // *********************************************************** 10 | 11 | // This function is called when a project is opened or re-opened (e.g. due to 12 | // the project's config changing) 13 | 14 | const { preprocessTypescript } = require('@nrwl/cypress/plugins/preprocessor'); 15 | 16 | module.exports = (on, config) => { 17 | // `on` is used to hook into various events Cypress emits 18 | // `config` is the resolved Cypress config 19 | 20 | // Preprocess Typescript file using Nx helper 21 | on('file:preprocessor', preprocessTypescript(config)); 22 | }; 23 | -------------------------------------------------------------------------------- /apps/shell-e2e/src/support/app.po.ts: -------------------------------------------------------------------------------- 1 | export const getGreeting = () => cy.get('h1'); 2 | -------------------------------------------------------------------------------- /apps/shell-e2e/src/support/commands.ts: -------------------------------------------------------------------------------- 1 | // *********************************************** 2 | // This example commands.js shows you how to 3 | // create various custom commands and overwrite 4 | // existing commands. 5 | // 6 | // For more comprehensive examples of custom 7 | // commands please read more here: 8 | // https://on.cypress.io/custom-commands 9 | // *********************************************** 10 | 11 | // eslint-disable-next-line @typescript-eslint/no-namespace 12 | declare namespace Cypress { 13 | // eslint-disable-next-line @typescript-eslint/no-unused-vars 14 | interface Chainable { 15 | login(email: string, password: string): void; 16 | } 17 | } 18 | // 19 | // -- This is a parent command -- 20 | Cypress.Commands.add('login', (email, password) => { 21 | console.log('Custom command example: Login', email, password); 22 | }); 23 | // 24 | // -- This is a child command -- 25 | // Cypress.Commands.add("drag", { prevSubject: 'element'}, (subject, options) => { ... }) 26 | // 27 | // 28 | // -- This is a dual command -- 29 | // Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... }) 30 | // 31 | // 32 | // -- This will overwrite an existing command -- 33 | // Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... }) 34 | -------------------------------------------------------------------------------- /apps/shell-e2e/src/support/index.ts: -------------------------------------------------------------------------------- 1 | // *********************************************************** 2 | // This example support/index.js is processed and 3 | // loaded automatically before your test files. 4 | // 5 | // This is a great place to put global configuration and 6 | // behavior that modifies Cypress. 7 | // 8 | // You can change the location of this file or turn off 9 | // automatically serving support files with the 10 | // 'supportFile' configuration option. 11 | // 12 | // You can read more here: 13 | // https://on.cypress.io/configuration 14 | // *********************************************************** 15 | 16 | // Import commands.js using ES2015 syntax: 17 | import './commands'; 18 | -------------------------------------------------------------------------------- /apps/shell-e2e/tsconfig.e2e.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "sourceMap": false, 5 | "outDir": "../../dist/out-tsc", 6 | "allowJs": true, 7 | "types": ["cypress", "node"], 8 | "forceConsistentCasingInFileNames": true, 9 | "strict": true, 10 | "noImplicitReturns": true, 11 | "noFallthroughCasesInSwitch": true 12 | }, 13 | "include": ["src/**/*.ts", "src/**/*.js"], 14 | "angularCompilerOptions": { 15 | "strictInjectionParameters": true, 16 | "strictInputAccessModifiers": true, 17 | "strictTemplates": true 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /apps/shell-e2e/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base.json", 3 | "files": [], 4 | "include": [], 5 | "references": [ 6 | { 7 | "path": "./tsconfig.e2e.json" 8 | } 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /apps/shell/.browserslistrc: -------------------------------------------------------------------------------- 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 | # For the full list of supported browsers by the Angular framework, please see: 6 | # https://angular.io/guide/browser-support 7 | 8 | # You can see what browsers were selected by your queries by running: 9 | # npx browserslist 10 | 11 | last 1 Chrome version 12 | last 1 Firefox version 13 | last 2 Edge major versions 14 | last 2 Safari major versions 15 | last 2 iOS major versions 16 | Firefox ESR 17 | not IE 11 # Angular supports IE 11 only as an opt-in. To opt-in, remove the 'not' prefix on this line. 18 | -------------------------------------------------------------------------------- /apps/shell/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["../../.eslintrc.json"], 3 | "ignorePatterns": ["!**/*"], 4 | "overrides": [ 5 | { 6 | "files": ["*.ts"], 7 | "extends": [ 8 | "plugin:@nrwl/nx/angular", 9 | "plugin:@angular-eslint/template/process-inline-templates" 10 | ], 11 | "rules": { 12 | "@angular-eslint/directive-selector": [ 13 | "error", 14 | { 15 | "type": "attribute", 16 | "prefix": "mfes", 17 | "style": "camelCase" 18 | } 19 | ], 20 | "@angular-eslint/component-selector": [ 21 | "error", 22 | { 23 | "type": "element", 24 | "prefix": "mfes", 25 | "style": "kebab-case" 26 | } 27 | ] 28 | } 29 | }, 30 | { 31 | "files": ["*.html"], 32 | "extends": ["plugin:@nrwl/nx/angular-template"], 33 | "rules": {} 34 | } 35 | ] 36 | } 37 | -------------------------------------------------------------------------------- /apps/shell/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | displayName: 'shell', 3 | preset: '../../jest.preset.js', 4 | setupFilesAfterEnv: ['/src/test-setup.ts'], 5 | globals: { 6 | 'ts-jest': { 7 | tsconfig: '/tsconfig.spec.json', 8 | stringifyContentPathRegex: '\\.(html|svg)$', 9 | }, 10 | }, 11 | coverageDirectory: '../../coverage/apps/shell', 12 | transform: { 13 | '^.+\\.(ts|js|html)$': 'jest-preset-angular', 14 | }, 15 | snapshotSerializers: [ 16 | 'jest-preset-angular/build/serializers/no-ng-attributes', 17 | 'jest-preset-angular/build/serializers/ng-snapshot', 18 | 'jest-preset-angular/build/serializers/html-comment', 19 | ], 20 | }; 21 | -------------------------------------------------------------------------------- /apps/shell/src/app/app.component.html: -------------------------------------------------------------------------------- 1 |
2 |

Welcome to {{ title }}!

3 |
4 |
5 | 10 | 11 |
12 | -------------------------------------------------------------------------------- /apps/shell/src/app/app.component.scss: -------------------------------------------------------------------------------- 1 | .main-nav { 2 | display: flex; 3 | gap: 10px; 4 | } -------------------------------------------------------------------------------- /apps/shell/src/app/app.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed } from '@angular/core/testing'; 2 | import { AppComponent } from './app.component'; 3 | 4 | describe('AppComponent', () => { 5 | beforeEach(async () => { 6 | await TestBed.configureTestingModule({ 7 | declarations: [AppComponent], 8 | }).compileComponents(); 9 | }); 10 | 11 | it('should create the app', () => { 12 | const fixture = TestBed.createComponent(AppComponent); 13 | const app = fixture.componentInstance; 14 | expect(app).toBeTruthy(); 15 | }); 16 | 17 | it(`should have as title 'shell'`, () => { 18 | const fixture = TestBed.createComponent(AppComponent); 19 | const app = fixture.componentInstance; 20 | expect(app.title).toEqual('shell'); 21 | }); 22 | 23 | it('should render title', () => { 24 | const fixture = TestBed.createComponent(AppComponent); 25 | fixture.detectChanges(); 26 | const compiled = fixture.nativeElement as HTMLElement; 27 | expect(compiled.querySelector('h1')?.textContent).toContain( 28 | 'Welcome to shell!' 29 | ); 30 | }); 31 | }); 32 | -------------------------------------------------------------------------------- /apps/shell/src/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'mfes-root', 5 | templateUrl: './app.component.html', 6 | styleUrls: ['./app.component.scss'], 7 | }) 8 | export class AppComponent { 9 | title = 'shell app'; 10 | } 11 | -------------------------------------------------------------------------------- /apps/shell/src/app/app.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { BrowserModule } from '@angular/platform-browser'; 3 | import { RouterModule } from '@angular/router'; 4 | 5 | import { AppComponent } from './app.component'; 6 | 7 | @NgModule({ 8 | declarations: [AppComponent], 9 | imports: [ 10 | BrowserModule, 11 | RouterModule.forRoot([ 12 | { 13 | path: 'mailbox', 14 | loadChildren: () => import('mailbox/MailboxModule').then(m => m.MailboxModule) 15 | }, 16 | { 17 | path: 'calendar', 18 | loadChildren: () => import('calendar/CalendarModule').then(m => m.CalendarModule) 19 | } 20 | ]) 21 | ], 22 | providers: [], 23 | bootstrap: [AppComponent], 24 | }) 25 | export class AppModule {} 26 | -------------------------------------------------------------------------------- /apps/shell/src/app/typed.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'mailbox/MailboxModule'; 2 | declare module 'calendar/CalendarModule'; -------------------------------------------------------------------------------- /apps/shell/src/assets/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tieppt/nx-micro-frontends/62a0c5ab20489fc0d7bd50710fc6ae097418f137/apps/shell/src/assets/.gitkeep -------------------------------------------------------------------------------- /apps/shell/src/bootstrap.ts: -------------------------------------------------------------------------------- 1 | import { enableProdMode } from '@angular/core'; 2 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 3 | 4 | import { AppModule } from './app/app.module'; 5 | import { environment } from './environments/environment'; 6 | 7 | if (environment.production) { 8 | enableProdMode(); 9 | } 10 | 11 | platformBrowserDynamic() 12 | .bootstrapModule(AppModule) 13 | .catch((err) => console.error(err)); 14 | -------------------------------------------------------------------------------- /apps/shell/src/environments/environment.prod.ts: -------------------------------------------------------------------------------- 1 | export const environment = { 2 | production: true, 3 | }; 4 | -------------------------------------------------------------------------------- /apps/shell/src/environments/environment.ts: -------------------------------------------------------------------------------- 1 | // This file can be replaced during build by using the `fileReplacements` array. 2 | // `ng build` 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/plugins/zone-error'; // Included with Angular CLI. 17 | -------------------------------------------------------------------------------- /apps/shell/src/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tieppt/nx-micro-frontends/62a0c5ab20489fc0d7bd50710fc6ae097418f137/apps/shell/src/favicon.ico -------------------------------------------------------------------------------- /apps/shell/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Shell 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /apps/shell/src/main.ts: -------------------------------------------------------------------------------- 1 | import('./bootstrap'); 2 | -------------------------------------------------------------------------------- /apps/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 | * IE11 requires the following for NgClass support on SVG elements 23 | */ 24 | // import 'classlist.js'; // Run `npm install --save classlist.js`. 25 | 26 | /** 27 | * Web Animations `@angular/platform-browser/animations` 28 | * Only required if AnimationBuilder is used within the application and using IE/Edge or Safari. 29 | * Standard animation support in Angular DOES NOT require any polyfills (as of Angular 6.0). 30 | */ 31 | // import 'web-animations-js'; // Run `npm install --save web-animations-js`. 32 | 33 | /** 34 | * By default, zone.js will patch all possible macroTask and DomEvents 35 | * user can disable parts of macroTask/DomEvents patch by setting following flags 36 | * because those flags need to be set before `zone.js` being loaded, and webpack 37 | * will put import in the top of bundle, so user need to create a separate file 38 | * in this directory (for example: zone-flags.ts), and put the following flags 39 | * into that file, and then add the following code before importing zone.js. 40 | * import './zone-flags'; 41 | * 42 | * The flags allowed in zone-flags.ts are listed here. 43 | * 44 | * The following flags will work for all browsers. 45 | * 46 | * (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame 47 | * (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick 48 | * (window as any).__zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames 49 | * 50 | * in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js 51 | * with the following flag, it will bypass `zone.js` patch for IE/Edge 52 | * 53 | * (window as any).__Zone_enable_cross_context_check = true; 54 | * 55 | */ 56 | 57 | /*************************************************************************************************** 58 | * Zone JS is required by default for Angular itself. 59 | */ 60 | import 'zone.js'; // Included with Angular CLI. 61 | 62 | /*************************************************************************************************** 63 | * APPLICATION IMPORTS 64 | */ 65 | -------------------------------------------------------------------------------- /apps/shell/src/styles.scss: -------------------------------------------------------------------------------- 1 | /* You can add global styles to this file, and also import other style files */ 2 | html, 3 | body { 4 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; 5 | } -------------------------------------------------------------------------------- /apps/shell/src/test-setup.ts: -------------------------------------------------------------------------------- 1 | import 'jest-preset-angular/setup-jest'; 2 | -------------------------------------------------------------------------------- /apps/shell/tsconfig.app.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "types": [] 6 | }, 7 | "files": ["src/main.ts", "src/polyfills.ts"], 8 | "include": ["src/**/*.d.ts"] 9 | } 10 | -------------------------------------------------------------------------------- /apps/shell/tsconfig.editor.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "include": ["**/*.ts"], 4 | "compilerOptions": { 5 | "types": ["jest", "node"] 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /apps/shell/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base.json", 3 | "files": [], 4 | "include": [], 5 | "references": [ 6 | { 7 | "path": "./tsconfig.app.json" 8 | }, 9 | { 10 | "path": "./tsconfig.spec.json" 11 | }, 12 | { 13 | "path": "./tsconfig.editor.json" 14 | } 15 | ], 16 | "compilerOptions": { 17 | "forceConsistentCasingInFileNames": true, 18 | "strict": true, 19 | "noImplicitReturns": true, 20 | "noFallthroughCasesInSwitch": true 21 | }, 22 | "angularCompilerOptions": { 23 | "strictInjectionParameters": true, 24 | "strictInputAccessModifiers": true, 25 | "strictTemplates": true 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /apps/shell/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "module": "commonjs", 6 | "types": ["jest", "node"] 7 | }, 8 | "files": ["src/test-setup.ts"], 9 | "include": ["**/*.spec.ts", "**/*.d.ts"] 10 | } 11 | -------------------------------------------------------------------------------- /apps/shell/webpack.config.js: -------------------------------------------------------------------------------- 1 | const { ModuleFederationPlugin } = require('webpack').container; 2 | 3 | module.exports = { 4 | output: { 5 | publicPath: "http://localhost:5200/", 6 | uniqueName: "shell" 7 | }, 8 | optimization: { 9 | runtimeChunk: false 10 | }, 11 | plugins: [ 12 | new ModuleFederationPlugin({ 13 | remotes: { 14 | 'mailbox': "mailbox@http://localhost:5300/remoteEntry.js", 15 | 'calendar': "calendar@http://localhost:5400/remoteEntry.js", 16 | }, 17 | shared: ["@angular/core", "@angular/common", "@angular/router"] 18 | }) 19 | ], 20 | }; 21 | -------------------------------------------------------------------------------- /apps/shell/webpack.prod.config.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./webpack.config'); 2 | -------------------------------------------------------------------------------- /decorate-angular-cli.js: -------------------------------------------------------------------------------- 1 | /** 2 | * This file decorates the Angular CLI with the Nx CLI to enable features such as computation caching 3 | * and faster execution of tasks. 4 | * 5 | * It does this by: 6 | * 7 | * - Patching the Angular CLI to warn you in case you accidentally use the undecorated ng command. 8 | * - Symlinking the ng to nx command, so all commands run through the Nx CLI 9 | * - Updating the package.json postinstall script to give you control over this script 10 | * 11 | * The Nx CLI decorates the Angular CLI, so the Nx CLI is fully compatible with it. 12 | * Every command you run should work the same when using the Nx CLI, except faster. 13 | * 14 | * Because of symlinking you can still type `ng build/test/lint` in the terminal. The ng command, in this case, 15 | * will point to nx, which will perform optimizations before invoking ng. So the Angular CLI is always invoked. 16 | * The Nx CLI simply does some optimizations before invoking the Angular CLI. 17 | * 18 | * To opt out of this patch: 19 | * - Replace occurrences of nx with ng in your package.json 20 | * - Remove the script from your postinstall script in your package.json 21 | * - Delete and reinstall your node_modules 22 | */ 23 | 24 | const fs = require('fs'); 25 | const os = require('os'); 26 | const cp = require('child_process'); 27 | const isWindows = os.platform() === 'win32'; 28 | let output; 29 | try { 30 | output = require('@nrwl/workspace').output; 31 | } catch (e) { 32 | console.warn('Angular CLI could not be decorated to enable computation caching. Please ensure @nrwl/workspace is installed.'); 33 | process.exit(0); 34 | } 35 | 36 | /** 37 | * Symlink of ng to nx, so you can keep using `ng build/test/lint` and still 38 | * invoke the Nx CLI and get the benefits of computation caching. 39 | */ 40 | function symlinkNgCLItoNxCLI() { 41 | try { 42 | const ngPath = './node_modules/.bin/ng'; 43 | const nxPath = './node_modules/.bin/nx'; 44 | if (isWindows) { 45 | /** 46 | * This is the most reliable way to create symlink-like behavior on Windows. 47 | * Such that it works in all shells and works with npx. 48 | */ 49 | ['', '.cmd', '.ps1'].forEach(ext => { 50 | if (fs.existsSync(nxPath + ext)) fs.writeFileSync(ngPath + ext, fs.readFileSync(nxPath + ext)); 51 | }); 52 | } else { 53 | // If unix-based, symlink 54 | cp.execSync(`ln -sf ./nx ${ngPath}`); 55 | } 56 | } 57 | catch(e) { 58 | output.error({ title: 'Unable to create a symlink from the Angular CLI to the Nx CLI:' + e.message }); 59 | throw e; 60 | } 61 | } 62 | 63 | try { 64 | symlinkNgCLItoNxCLI(); 65 | require('@nrwl/cli/lib/decorate-cli').decorateCli(); 66 | output.log({ title: 'Angular CLI has been decorated to enable computation caching.' }); 67 | } catch(e) { 68 | output.error({ title: 'Decoration of the Angular CLI did not complete successfully' }); 69 | } 70 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | const { getJestProjects } = require('@nrwl/jest'); 2 | 3 | module.exports = { 4 | projects: getJestProjects(), 5 | }; 6 | -------------------------------------------------------------------------------- /jest.preset.js: -------------------------------------------------------------------------------- 1 | const nxPreset = require('@nrwl/jest/preset'); 2 | 3 | module.exports = { ...nxPreset }; 4 | -------------------------------------------------------------------------------- /libs/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tieppt/nx-micro-frontends/62a0c5ab20489fc0d7bd50710fc6ae097418f137/libs/.gitkeep -------------------------------------------------------------------------------- /nx.json: -------------------------------------------------------------------------------- 1 | { 2 | "npmScope": "mfes", 3 | "affected": { 4 | "defaultBase": "master" 5 | }, 6 | "implicitDependencies": { 7 | "package.json": { 8 | "dependencies": "*", 9 | "devDependencies": "*" 10 | }, 11 | ".eslintrc.json": "*" 12 | }, 13 | "tasksRunnerOptions": { 14 | "default": { 15 | "runner": "@nrwl/workspace/tasks-runners/default", 16 | "options": { 17 | "cacheableOperations": ["build", "lint", "test", "e2e"] 18 | } 19 | } 20 | }, 21 | "targetDependencies": { 22 | "build": [ 23 | { 24 | "target": "build", 25 | "projects": "dependencies" 26 | } 27 | ] 28 | }, 29 | "projects": { 30 | "calendar": { 31 | "tags": [] 32 | }, 33 | "calendar-e2e": { 34 | "tags": [], 35 | "implicitDependencies": ["calendar"] 36 | }, 37 | "mailbox": { 38 | "tags": [] 39 | }, 40 | "mailbox-e2e": { 41 | "tags": [], 42 | "implicitDependencies": ["mailbox"] 43 | }, 44 | "shell": { 45 | "tags": [] 46 | }, 47 | "shell-e2e": { 48 | "tags": [], 49 | "implicitDependencies": ["shell"] 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mfes", 3 | "version": "0.0.0", 4 | "license": "MIT", 5 | "scripts": { 6 | "ng": "nx", 7 | "postinstall": "node ./decorate-angular-cli.js && ngcc --properties es2015 browser module main", 8 | "nx": "nx", 9 | "start": "ng serve", 10 | "build": "ng build", 11 | "test": "ng test", 12 | "lint": "nx workspace-lint && ng lint", 13 | "e2e": "ng e2e", 14 | "start:shell": "ng serve --project=shell --port 5200", 15 | "start:mailbox": "ng serve --project=mailbox --port 5300", 16 | "start:calendar": "ng serve --project=calendar --port 5400", 17 | "affected:apps": "nx affected:apps", 18 | "affected:libs": "nx affected:libs", 19 | "affected:build": "nx affected:build", 20 | "affected:e2e": "nx affected:e2e", 21 | "affected:test": "nx affected:test", 22 | "affected:lint": "nx affected:lint", 23 | "affected:dep-graph": "nx affected:dep-graph", 24 | "affected": "nx affected", 25 | "format": "nx format:write", 26 | "format:write": "nx format:write", 27 | "format:check": "nx format:check", 28 | "update": "nx migrate latest", 29 | "workspace-generator": "nx workspace-generator", 30 | "dep-graph": "nx dep-graph", 31 | "help": "nx help" 32 | }, 33 | "private": true, 34 | "dependencies": { 35 | "@angular/animations": "^12.2.0", 36 | "@angular/common": "^12.2.0", 37 | "@angular/compiler": "^12.2.0", 38 | "@angular/core": "^12.2.0", 39 | "@angular/forms": "^12.2.0", 40 | "@angular/platform-browser": "^12.2.0", 41 | "@angular/platform-browser-dynamic": "^12.2.0", 42 | "@angular/router": "^12.2.0", 43 | "@nrwl/angular": "12.7.1", 44 | "rxjs": "~6.6.0", 45 | "tslib": "^2.0.0", 46 | "zone.js": "~0.11.4" 47 | }, 48 | "devDependencies": { 49 | "@angular-builders/custom-webpack": "^12.1.0", 50 | "@angular-devkit/build-angular": "~12.2.0", 51 | "@angular-eslint/eslint-plugin": "~12.3.0", 52 | "@angular-eslint/eslint-plugin-template": "~12.3.0", 53 | "@angular-eslint/template-parser": "~12.3.0", 54 | "@angular/cli": "~12.2.0", 55 | "@angular/compiler-cli": "^12.2.0", 56 | "@angular/language-service": "^12.2.0", 57 | "@nrwl/cli": "12.7.1", 58 | "@nrwl/cypress": "12.7.1", 59 | "@nrwl/eslint-plugin-nx": "12.7.1", 60 | "@nrwl/jest": "12.7.1", 61 | "@nrwl/linter": "12.7.1", 62 | "@nrwl/tao": "12.7.1", 63 | "@nrwl/workspace": "12.7.1", 64 | "@types/jest": "26.0.24", 65 | "@types/node": "14.14.33", 66 | "@typescript-eslint/eslint-plugin": "~4.28.3", 67 | "@typescript-eslint/parser": "~4.28.3", 68 | "cypress": "^7.3.0", 69 | "dotenv": "10.0.0", 70 | "eslint": "7.22.0", 71 | "eslint-config-prettier": "8.1.0", 72 | "eslint-plugin-cypress": "^2.10.3", 73 | "jest": "27.0.3", 74 | "jest-preset-angular": "9.0.4", 75 | "prettier": "^2.3.1", 76 | "terser-webpack-plugin": "^5.1.3", 77 | "ts-jest": "27.0.3", 78 | "ts-node": "~9.1.1", 79 | "typescript": "~4.3.5", 80 | "webpack": "^5.49.0" 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /tools/generators/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tieppt/nx-micro-frontends/62a0c5ab20489fc0d7bd50710fc6ae097418f137/tools/generators/.gitkeep -------------------------------------------------------------------------------- /tools/tsconfig.tools.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.base.json", 3 | "compilerOptions": { 4 | "outDir": "../dist/out-tsc/tools", 5 | "rootDir": ".", 6 | "module": "commonjs", 7 | "target": "es5", 8 | "types": ["node"], 9 | "importHelpers": false 10 | }, 11 | "include": ["**/*.ts"] 12 | } 13 | -------------------------------------------------------------------------------- /tsconfig.base.json: -------------------------------------------------------------------------------- 1 | { 2 | "compileOnSave": false, 3 | "compilerOptions": { 4 | "rootDir": ".", 5 | "sourceMap": true, 6 | "declaration": false, 7 | "moduleResolution": "node", 8 | "emitDecoratorMetadata": true, 9 | "experimentalDecorators": true, 10 | "importHelpers": true, 11 | "target": "es2015", 12 | "module": "esnext", 13 | "lib": ["es2017", "dom"], 14 | "skipLibCheck": true, 15 | "skipDefaultLibCheck": true, 16 | "baseUrl": ".", 17 | "paths": {} 18 | }, 19 | "exclude": ["node_modules", "tmp"] 20 | } 21 | --------------------------------------------------------------------------------