├── mfe1 ├── src │ ├── assets │ │ ├── .gitkeep │ │ ├── vite.svg │ │ └── analog.svg │ ├── vite-env.d.ts │ ├── environments │ │ ├── environment.prod.ts │ │ └── environment.ts │ ├── favicon.ico │ ├── main.ts │ ├── bootstrap.ts │ ├── test.ts │ ├── index.html │ ├── app │ │ ├── app.component.ts │ │ └── app.component.spec.ts │ ├── styles.css │ └── polyfills.ts ├── .vscode │ ├── extensions.json │ ├── launch.json │ └── tasks.json ├── .editorconfig ├── tsconfig.app.json ├── update.bat ├── tsconfig.spec.json ├── federation.config.cjs ├── angular.json ├── .browserslistrc ├── README.md ├── tsconfig.json ├── package.json └── vite.config.ts ├── shell ├── src │ ├── assets │ │ ├── .gitkeep │ │ ├── vite.svg │ │ └── analog.svg │ ├── vite-env.d.ts │ ├── environments │ │ ├── environment.prod.ts │ │ └── environment.ts │ ├── favicon.ico │ ├── app │ │ ├── home.component.ts │ │ ├── app.routes.ts │ │ ├── app.component.ts │ │ └── app.component.spec.ts │ ├── main.ts │ ├── test.ts │ ├── bootstrap.ts │ ├── index.html │ ├── styles.css │ └── polyfills.ts ├── .vscode │ ├── extensions.json │ ├── launch.json │ └── tasks.json ├── federation.config.cjs ├── tsconfig.app.json ├── update.bat ├── .editorconfig ├── tsconfig.spec.json ├── angular.json ├── .browserslistrc ├── README.md ├── tsconfig.json ├── package.json └── vite.config.ts ├── .gitignore ├── shared └── index.ts ├── example.png └── readme.md /mfe1/src/assets/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /shell/src/assets/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | -------------------------------------------------------------------------------- /mfe1/src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /shared/index.ts: -------------------------------------------------------------------------------- 1 | export const shared = { 2 | userName: '' 3 | }; -------------------------------------------------------------------------------- /shell/src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/manfredsteyer/native-federation-vite-angular-demo/HEAD/example.png -------------------------------------------------------------------------------- /mfe1/src/environments/environment.prod.ts: -------------------------------------------------------------------------------- 1 | export const environment = { 2 | production: true 3 | }; 4 | -------------------------------------------------------------------------------- /shell/src/environments/environment.prod.ts: -------------------------------------------------------------------------------- 1 | export const environment = { 2 | production: true 3 | }; 4 | -------------------------------------------------------------------------------- /mfe1/src/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/manfredsteyer/native-federation-vite-angular-demo/HEAD/mfe1/src/favicon.ico -------------------------------------------------------------------------------- /shell/src/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/manfredsteyer/native-federation-vite-angular-demo/HEAD/shell/src/favicon.ico -------------------------------------------------------------------------------- /mfe1/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=827846 3 | "recommendations": ["angular.ng-template"] 4 | } 5 | -------------------------------------------------------------------------------- /shell/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=827846 3 | "recommendations": ["angular.ng-template"] 4 | } 5 | -------------------------------------------------------------------------------- /mfe1/src/main.ts: -------------------------------------------------------------------------------- 1 | import { initFederation } from "@softarc/native-federation"; 2 | 3 | (async () => { 4 | 5 | await initFederation(); 6 | await import('./bootstrap'); 7 | 8 | })(); -------------------------------------------------------------------------------- /shell/src/app/home.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | 3 | @Component({ 4 | standalone: true, 5 | selector: 'app-home', 6 | template: `

Welcome!

`, 7 | }) 8 | export class HomeComponent {} 9 | -------------------------------------------------------------------------------- /shell/src/main.ts: -------------------------------------------------------------------------------- 1 | import { initFederation } from "@softarc/native-federation"; 2 | 3 | (async () => { 4 | 5 | await initFederation({ 6 | 'mfe1': 'http://localhost:3001/remoteEntry.json' 7 | }); 8 | 9 | await import('./bootstrap'); 10 | 11 | })(); -------------------------------------------------------------------------------- /shell/federation.config.cjs: -------------------------------------------------------------------------------- 1 | const { 2 | withNativeFederation, 3 | shareAll, 4 | } = require("@softarc/native-federation/build"); 5 | 6 | module.exports = withNativeFederation({ 7 | name: "host", 8 | 9 | shared: { 10 | ...shareAll({ singleton: true, strictVersion: true, requiredVersion: "auto", }), 11 | }, 12 | 13 | }); 14 | -------------------------------------------------------------------------------- /mfe1/src/bootstrap.ts: -------------------------------------------------------------------------------- 1 | import './polyfills'; 2 | import { enableProdMode } from '@angular/core'; 3 | import { bootstrapApplication } from '@angular/platform-browser'; 4 | 5 | import { AppComponent } from './app/app.component'; 6 | 7 | if (import.meta.env.PROD) { 8 | enableProdMode(); 9 | } 10 | 11 | bootstrapApplication(AppComponent); 12 | -------------------------------------------------------------------------------- /mfe1/.editorconfig: -------------------------------------------------------------------------------- 1 | # Editor configuration, see https://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 2 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.ts] 12 | quote_type = single 13 | 14 | [*.md] 15 | max_line_length = off 16 | trim_trailing_whitespace = false 17 | -------------------------------------------------------------------------------- /mfe1/tsconfig.app.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "extends": "./tsconfig.json", 4 | "compilerOptions": { 5 | "composite": false, 6 | "outDir": "./out-tsc/app", 7 | "types": [] 8 | }, 9 | "files": ["src/main.ts", "src/polyfills.ts"], 10 | "include": ["src/**/*.d.ts"] 11 | } 12 | -------------------------------------------------------------------------------- /shell/tsconfig.app.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "extends": "./tsconfig.json", 4 | "compilerOptions": { 5 | "composite": false, 6 | "outDir": "./out-tsc/app", 7 | "types": [] 8 | }, 9 | "files": ["src/main.ts", "src/polyfills.ts"], 10 | "include": ["src/**/*.d.ts"] 11 | } 12 | -------------------------------------------------------------------------------- /shell/update.bat: -------------------------------------------------------------------------------- 1 | call npm i @softarc/native-federation@latest --registry http://localhost:4873 2 | call npm i @softarc/native-federation-runtime@latest --registry http://localhost:4873 3 | call npm i @softarc/native-federation-esbuild@latest --registry http://localhost:4873 4 | call npm i @angular-architects/native-federation@latest --registry http://localhost:4873 5 | -------------------------------------------------------------------------------- /shell/.editorconfig: -------------------------------------------------------------------------------- 1 | # Editor configuration, see https://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 2 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.ts] 12 | quote_type = single 13 | 14 | [*.md] 15 | max_line_length = off 16 | trim_trailing_whitespace = false 17 | -------------------------------------------------------------------------------- /mfe1/update.bat: -------------------------------------------------------------------------------- 1 | call npm i @softarc/native-federation@latest --registry http://localhost:4873 -f 2 | call npm i @softarc/native-federation-runtime@latest --registry http://localhost:4873 -f 3 | call npm i @softarc/native-federation-esbuild@latest --registry http://localhost:4873 -f 4 | call npm i @angular-architects/native-federation@latest --registry http://localhost:4873 -f 5 | 6 | -------------------------------------------------------------------------------- /mfe1/src/test.ts: -------------------------------------------------------------------------------- 1 | import '@analogjs/vite-plugin-angular/setup-vitest'; 2 | 3 | import { 4 | BrowserDynamicTestingModule, 5 | platformBrowserDynamicTesting, 6 | } from '@angular/platform-browser-dynamic/testing'; 7 | import { getTestBed } from '@angular/core/testing'; 8 | 9 | getTestBed().initTestEnvironment( 10 | BrowserDynamicTestingModule, 11 | platformBrowserDynamicTesting() 12 | ); 13 | -------------------------------------------------------------------------------- /mfe1/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "extends": "./tsconfig.json", 4 | "compilerOptions": { 5 | "composite": false, 6 | "outDir": "./out-tsc/spec", 7 | "types": ["node", "vitest/globals"] 8 | }, 9 | "files": ["src/test.ts", "src/polyfills.ts"], 10 | "include": ["src/**/*.spec.ts", "src/**/*.ts"] 11 | } 12 | -------------------------------------------------------------------------------- /shell/src/test.ts: -------------------------------------------------------------------------------- 1 | import '@analogjs/vite-plugin-angular/setup-vitest'; 2 | 3 | import { 4 | BrowserDynamicTestingModule, 5 | platformBrowserDynamicTesting, 6 | } from '@angular/platform-browser-dynamic/testing'; 7 | import { getTestBed } from '@angular/core/testing'; 8 | 9 | getTestBed().initTestEnvironment( 10 | BrowserDynamicTestingModule, 11 | platformBrowserDynamicTesting() 12 | ); 13 | -------------------------------------------------------------------------------- /shell/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "extends": "./tsconfig.json", 4 | "compilerOptions": { 5 | "composite": false, 6 | "outDir": "./out-tsc/spec", 7 | "types": ["node", "vitest/globals"] 8 | }, 9 | "files": ["src/test.ts", "src/polyfills.ts"], 10 | "include": ["src/**/*.spec.ts", "src/**/*.ts"] 11 | } 12 | -------------------------------------------------------------------------------- /mfe1/federation.config.cjs: -------------------------------------------------------------------------------- 1 | const { 2 | withNativeFederation, 3 | shareAll, 4 | } = require("@softarc/native-federation/build"); 5 | 6 | module.exports = withNativeFederation({ 7 | name: "host", 8 | 9 | exposes: { 10 | "./comp": "src/app/app.component.ts" 11 | }, 12 | 13 | shared: { 14 | ...shareAll({ singleton: true, strictVersion: true, requiredVersion: "auto", }), 15 | }, 16 | 17 | }); 18 | -------------------------------------------------------------------------------- /mfe1/angular.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "./node_modules/@angular/cli/lib/config/schema.json", 3 | "version": 1, 4 | "newProjectRoot": "projects", 5 | "projects": { 6 | "my-app": { 7 | "projectType": "application", 8 | "schematics": {}, 9 | "root": "", 10 | "sourceRoot": "src", 11 | "prefix": "app", 12 | "architect": { 13 | "targets": {} 14 | } 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /shell/angular.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "./node_modules/@angular/cli/lib/config/schema.json", 3 | "version": 1, 4 | "newProjectRoot": "projects", 5 | "projects": { 6 | "my-app": { 7 | "projectType": "application", 8 | "schematics": {}, 9 | "root": "", 10 | "sourceRoot": "src", 11 | "prefix": "app", 12 | "architect": { 13 | "targets": {} 14 | } 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /shell/src/bootstrap.ts: -------------------------------------------------------------------------------- 1 | import './polyfills'; 2 | import { enableProdMode } from '@angular/core'; 3 | import { bootstrapApplication } from '@angular/platform-browser'; 4 | 5 | import { AppComponent } from './app/app.component'; 6 | import { provideRouter } from '@angular/router'; 7 | import { APP_ROUTES } from './app/app.routes'; 8 | 9 | if (import.meta.env.PROD) { 10 | enableProdMode(); 11 | } 12 | 13 | bootstrapApplication(AppComponent, { 14 | providers: [ 15 | provideRouter(APP_ROUTES,) 16 | ] 17 | }); 18 | -------------------------------------------------------------------------------- /mfe1/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 3 | "version": "0.2.0", 4 | "configurations": [ 5 | { 6 | "name": "ng serve", 7 | "type": "pwa-chrome", 8 | "request": "launch", 9 | "preLaunchTask": "npm: start", 10 | "url": "http://localhost:4200/" 11 | }, 12 | { 13 | "name": "ng test", 14 | "type": "chrome", 15 | "request": "launch", 16 | "preLaunchTask": "npm: test", 17 | "url": "http://localhost:9876/debug.html" 18 | } 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /shell/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 3 | "version": "0.2.0", 4 | "configurations": [ 5 | { 6 | "name": "ng serve", 7 | "type": "pwa-chrome", 8 | "request": "launch", 9 | "preLaunchTask": "npm: start", 10 | "url": "http://localhost:4200/" 11 | }, 12 | { 13 | "name": "ng test", 14 | "type": "chrome", 15 | "request": "launch", 16 | "preLaunchTask": "npm: test", 17 | "url": "http://localhost:9876/debug.html" 18 | } 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /shell/src/app/app.routes.ts: -------------------------------------------------------------------------------- 1 | import { Routes } from '@angular/router'; 2 | import { loadRemoteModule } from '@softarc/native-federation-runtime'; 3 | import { HomeComponent } from './home.component'; 4 | 5 | export const APP_ROUTES: Routes = [ 6 | { 7 | path: '', 8 | pathMatch: 'full', 9 | redirectTo: 'home', 10 | }, 11 | { 12 | path: 'home', 13 | component: HomeComponent, 14 | }, 15 | { 16 | path: 'mfe1', 17 | loadComponent: () => 18 | loadRemoteModule({ 19 | remoteName: 'mfe1', 20 | exposedModule: './comp', 21 | }).then((esm) => esm.AppComponent), 22 | }, 23 | ]; 24 | -------------------------------------------------------------------------------- /mfe1/.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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /mfe1/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | MFE1 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /shell/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Shell 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /mfe1/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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /mfe1/README.md: -------------------------------------------------------------------------------- 1 | # Analog App 2 | 3 | This project was generated with [Analog](https://npmjs.com/package/create-analog). 4 | 5 | ## Setup 6 | 7 | Run `yarn` to install the application dependencies. 8 | 9 | ## Development 10 | 11 | Run `yarn dev` for a dev server. Navigate to `http://localhost:5173/`. The application will automatically reload if you change any of the source files. 12 | 13 | ## Build 14 | 15 | Run `yarn build` to build the project. The build artifacts will be stored in the `dist/` directory. 16 | 17 | ## Test 18 | 19 | Run `yarn test` to run unit tests with [Vitest](https://vitest.dev). 20 | 21 | ## Community 22 | 23 | - Join the [Discord](https://discord.gg/mKC2Ec48U5) 24 | - Visit and Star the [GitHub Repo](https://github.com/analogjs/analog) 25 | - Visit the [Website](https://analogjs.org/) 26 | - Follow us on [Twitter](https://twitter.com/analogjs) 27 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # Example: Micro Frontends with Native Federation + vite + Angular powered by AnalogJS 2 | 3 | The section between the dashed lines is a separately compiled and deployed Micro Frontend: 4 | 5 | ![The section between the dashed lines is a separately compiled and deployed Micro Frontend](example.png) 6 | 7 | ## Install and Run 8 | 9 | Repeat this for both, the ``shell`` and the ``mfe1`` folder: 10 | 11 | ``` 12 | npm i 13 | npm run dev 14 | ``` 15 | 16 | ## Inspect the Examples 17 | 18 | - ``vite.config.ts``: Here, the federation-vite-plugin is used and the dev server is configured to allow access to the ``shared`` folder 19 | - ``federation.config``: Native Federation config 20 | - ``index.html``: Here, the polyfill for Import Maps is registered 21 | - ``main.ts``: Initializes Native Federation and then (!) imports ``bootstrap.ts`` for starting the application 22 | -------------------------------------------------------------------------------- /shell/README.md: -------------------------------------------------------------------------------- 1 | # Analog App 2 | 3 | This project was generated with [Analog](https://npmjs.com/package/create-analog). 4 | 5 | ## Setup 6 | 7 | Run `yarn` to install the application dependencies. 8 | 9 | ## Development 10 | 11 | Run `yarn dev` for a dev server. Navigate to `http://localhost:5173/`. The application will automatically reload if you change any of the source files. 12 | 13 | ## Build 14 | 15 | Run `yarn build` to build the project. The build artifacts will be stored in the `dist/` directory. 16 | 17 | ## Test 18 | 19 | Run `yarn test` to run unit tests with [Vitest](https://vitest.dev). 20 | 21 | ## Community 22 | 23 | - Join the [Discord](https://discord.gg/mKC2Ec48U5) 24 | - Visit and Star the [GitHub Repo](https://github.com/analogjs/analog) 25 | - Visit the [Website](https://analogjs.org/) 26 | - Follow us on [Twitter](https://twitter.com/analogjs) 27 | -------------------------------------------------------------------------------- /mfe1/src/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { shared } from 'shared'; 3 | 4 | @Component({ 5 | selector: 'app-root', 6 | standalone: true, 7 | template: ` 8 |
9 |

Flights

10 | 11 | 12 |
13 | `, 14 | styles: [ 15 | ` 16 | .mfe { 17 | border: 2px darkred dashed; 18 | padding: 20px; 19 | } 20 | 21 | input[type='text'] { 22 | width: 300px; 23 | } 24 | 25 | button, input[type='text'] { 26 | border-radius: 5px; 27 | border: black 1px solid; 28 | padding: 8px 5px; 29 | margin: 8px 0; 30 | margin-right:10px; 31 | box-sizing: border-box; 32 | } 33 | `, 34 | ], 35 | }) 36 | export class AppComponent { 37 | constructor() { 38 | console.log('mfe1:user name', shared.userName) 39 | } 40 | search() { 41 | alert('Not implemented for this demo.'); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /shell/src/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import { CommonModule } from '@angular/common'; 2 | import { Component } from '@angular/core'; 3 | import { RouterLinkWithHref, RouterOutlet } from '@angular/router'; 4 | import { HomeComponent } from './home.component'; 5 | import { shared } from 'shared'; 6 | 7 | @Component({ 8 | selector: 'app-root', 9 | standalone: true, 10 | imports: [ 11 | HomeComponent, 12 | CommonModule, 13 | RouterLinkWithHref, 14 | RouterOutlet 15 | ], 16 | template: ` 17 | 21 |
22 | 23 |
24 | `, 25 | styles: [` 26 | 27 | .menu { 28 | background-color: black; 29 | padding:20px; 30 | } 31 | 32 | .menu a { 33 | color: white; 34 | font-size: 18px; 35 | margin-right: 20px; 36 | } 37 | 38 | main { 39 | padding: 20px; 40 | } 41 | `] 42 | }) 43 | export class AppComponent { 44 | constructor() { 45 | shared.userName = 'Jane Doe'; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /mfe1/.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | // For more information, visit: https://go.microsoft.com/fwlink/?LinkId=733558 3 | "version": "2.0.0", 4 | "tasks": [ 5 | { 6 | "type": "npm", 7 | "script": "start", 8 | "isBackground": true, 9 | "problemMatcher": { 10 | "owner": "typescript", 11 | "pattern": "$tsc", 12 | "background": { 13 | "activeOnStart": true, 14 | "beginsPattern": { 15 | "regexp": "(.*?)" 16 | }, 17 | "endsPattern": { 18 | "regexp": "bundle generation complete" 19 | } 20 | } 21 | } 22 | }, 23 | { 24 | "type": "npm", 25 | "script": "test", 26 | "isBackground": true, 27 | "problemMatcher": { 28 | "owner": "typescript", 29 | "pattern": "$tsc", 30 | "background": { 31 | "activeOnStart": true, 32 | "beginsPattern": { 33 | "regexp": "(.*?)" 34 | }, 35 | "endsPattern": { 36 | "regexp": "bundle generation complete" 37 | } 38 | } 39 | } 40 | } 41 | ] 42 | } 43 | -------------------------------------------------------------------------------- /shell/.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | // For more information, visit: https://go.microsoft.com/fwlink/?LinkId=733558 3 | "version": "2.0.0", 4 | "tasks": [ 5 | { 6 | "type": "npm", 7 | "script": "start", 8 | "isBackground": true, 9 | "problemMatcher": { 10 | "owner": "typescript", 11 | "pattern": "$tsc", 12 | "background": { 13 | "activeOnStart": true, 14 | "beginsPattern": { 15 | "regexp": "(.*?)" 16 | }, 17 | "endsPattern": { 18 | "regexp": "bundle generation complete" 19 | } 20 | } 21 | } 22 | }, 23 | { 24 | "type": "npm", 25 | "script": "test", 26 | "isBackground": true, 27 | "problemMatcher": { 28 | "owner": "typescript", 29 | "pattern": "$tsc", 30 | "background": { 31 | "activeOnStart": true, 32 | "beginsPattern": { 33 | "regexp": "(.*?)" 34 | }, 35 | "endsPattern": { 36 | "regexp": "bundle generation complete" 37 | } 38 | } 39 | } 40 | } 41 | ] 42 | } 43 | -------------------------------------------------------------------------------- /mfe1/tsconfig.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "compileOnSave": false, 4 | "compilerOptions": { 5 | "baseUrl": "./", 6 | "outDir": "./dist/out-tsc", 7 | "forceConsistentCasingInFileNames": true, 8 | "strict": true, 9 | "noImplicitOverride": true, 10 | "noPropertyAccessFromIndexSignature": true, 11 | "noImplicitReturns": true, 12 | "noFallthroughCasesInSwitch": true, 13 | "sourceMap": true, 14 | "declaration": false, 15 | "downlevelIteration": true, 16 | "experimentalDecorators": true, 17 | "moduleResolution": "node", 18 | "importHelpers": true, 19 | "target": "es2020", 20 | "module": "es2020", 21 | "lib": ["es2020", "dom"], 22 | "paths": { 23 | "shared": ["../shared/index.ts"] 24 | } 25 | }, 26 | "angularCompilerOptions": { 27 | "enableI18nLegacyMessageIdFormat": false, 28 | "strictInjectionParameters": true, 29 | "strictInputAccessModifiers": true, 30 | "strictTemplates": true 31 | }, 32 | "references": [ 33 | { "path": "tsconfig.app.json" }, 34 | { "path": "tsconfig.spec.json" } 35 | ] 36 | } 37 | -------------------------------------------------------------------------------- /shell/tsconfig.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "compileOnSave": false, 4 | "compilerOptions": { 5 | "baseUrl": "./", 6 | "outDir": "./dist/out-tsc", 7 | "forceConsistentCasingInFileNames": true, 8 | "strict": true, 9 | "noImplicitOverride": true, 10 | "noPropertyAccessFromIndexSignature": true, 11 | "noImplicitReturns": true, 12 | "noFallthroughCasesInSwitch": true, 13 | "sourceMap": true, 14 | "declaration": false, 15 | "downlevelIteration": true, 16 | "experimentalDecorators": true, 17 | "moduleResolution": "node", 18 | "importHelpers": true, 19 | "target": "es2020", 20 | "module": "es2020", 21 | "lib": ["es2020", "dom"], 22 | "paths": { 23 | "shared": ["../shared/index.ts"] 24 | } 25 | }, 26 | "angularCompilerOptions": { 27 | "enableI18nLegacyMessageIdFormat": false, 28 | "strictInjectionParameters": true, 29 | "strictInputAccessModifiers": true, 30 | "strictTemplates": true 31 | }, 32 | "references": [ 33 | { "path": "tsconfig.app.json" }, 34 | { "path": "tsconfig.spec.json" } 35 | ] 36 | } 37 | -------------------------------------------------------------------------------- /mfe1/src/app/app.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed } from '@angular/core/testing'; 2 | import { RouterTestingModule } from '@angular/router/testing'; 3 | import { AppComponent } from './app.component'; 4 | 5 | describe('AppComponent', () => { 6 | beforeEach(async () => { 7 | await TestBed.configureTestingModule({ 8 | imports: [ 9 | RouterTestingModule, 10 | AppComponent 11 | ] 12 | }).compileComponents(); 13 | }); 14 | 15 | it('should create the app', () => { 16 | const fixture = TestBed.createComponent(AppComponent); 17 | const app = fixture.componentInstance; 18 | expect(app).toBeTruthy(); 19 | }); 20 | 21 | it(`should have an initial count of 0`, () => { 22 | const fixture = TestBed.createComponent(AppComponent); 23 | const app = fixture.componentInstance; 24 | expect(app.count).toEqual(0); 25 | }); 26 | 27 | it('should render title', () => { 28 | const fixture = TestBed.createComponent(AppComponent); 29 | fixture.detectChanges(); 30 | const compiled = fixture.nativeElement as HTMLElement; 31 | expect(compiled.querySelector('h1')?.textContent).toContain('Vite + Angular'); 32 | }); 33 | }); 34 | -------------------------------------------------------------------------------- /shell/src/app/app.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed } from '@angular/core/testing'; 2 | import { RouterTestingModule } from '@angular/router/testing'; 3 | import { AppComponent } from './app.component'; 4 | 5 | describe('AppComponent', () => { 6 | beforeEach(async () => { 7 | await TestBed.configureTestingModule({ 8 | imports: [ 9 | RouterTestingModule, 10 | AppComponent 11 | ] 12 | }).compileComponents(); 13 | }); 14 | 15 | it('should create the app', () => { 16 | const fixture = TestBed.createComponent(AppComponent); 17 | const app = fixture.componentInstance; 18 | expect(app).toBeTruthy(); 19 | }); 20 | 21 | it(`should have an initial count of 0`, () => { 22 | const fixture = TestBed.createComponent(AppComponent); 23 | const app = fixture.componentInstance; 24 | expect(app.count).toEqual(0); 25 | }); 26 | 27 | it('should render title', () => { 28 | const fixture = TestBed.createComponent(AppComponent); 29 | fixture.detectChanges(); 30 | const compiled = fixture.nativeElement as HTMLElement; 31 | expect(compiled.querySelector('h1')?.textContent).toContain('Vite + Angular'); 32 | }); 33 | }); 34 | -------------------------------------------------------------------------------- /shell/src/styles.css: -------------------------------------------------------------------------------- 1 | /* You can add global styles to this file, and also import other style files */ 2 | /* You can add global styles to this file, and also import other style files */ 3 | :root { 4 | font-family: Inter, Avenir, Helvetica, Arial, sans-serif; 5 | font-size: 16px; 6 | line-height: 24px; 7 | font-weight: 400; 8 | 9 | color-scheme: light dark; 10 | color: rgba(255, 255, 255, 0.87); 11 | background-color: #242424; 12 | 13 | font-synthesis: none; 14 | text-rendering: optimizeLegibility; 15 | -webkit-font-smoothing: antialiased; 16 | -moz-osx-font-smoothing: grayscale; 17 | -webkit-text-size-adjust: 100%; 18 | } 19 | 20 | a { 21 | font-weight: 500; 22 | color: #646cff; 23 | text-decoration: inherit; 24 | } 25 | a:hover { 26 | color: #535bf2; 27 | } 28 | 29 | body { 30 | margin: 0; 31 | padding:0px; 32 | } 33 | 34 | h1 { 35 | font-size: 3.2em; 36 | line-height: 1.1; 37 | } 38 | 39 | .card { 40 | padding: 2em; 41 | } 42 | 43 | @media (prefers-color-scheme: light) { 44 | :root { 45 | color: #213547; 46 | background-color: #ffffff; 47 | } 48 | a:hover { 49 | color: #747bff; 50 | } 51 | button { 52 | background-color: #f9f9f9; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /mfe1/src/styles.css: -------------------------------------------------------------------------------- 1 | /* You can add global styles to this file, and also import other style files */ 2 | /* You can add global styles to this file, and also import other style files */ 3 | :root { 4 | font-family: Inter, Avenir, Helvetica, Arial, sans-serif; 5 | font-size: 16px; 6 | line-height: 24px; 7 | font-weight: 400; 8 | 9 | color-scheme: light dark; 10 | color: rgba(255, 255, 255, 0.87); 11 | background-color: #242424; 12 | 13 | font-synthesis: none; 14 | text-rendering: optimizeLegibility; 15 | -webkit-font-smoothing: antialiased; 16 | -moz-osx-font-smoothing: grayscale; 17 | -webkit-text-size-adjust: 100%; 18 | } 19 | 20 | a { 21 | font-weight: 500; 22 | color: #646cff; 23 | text-decoration: inherit; 24 | } 25 | a:hover { 26 | color: #535bf2; 27 | } 28 | 29 | body { 30 | margin: 0; 31 | /* display: flex; 32 | place-items: center; */ 33 | padding:20px; 34 | /* min-width: 320px; 35 | min-height: 100vh; */ 36 | } 37 | 38 | h1 { 39 | font-size: 3.2em; 40 | line-height: 1.1; 41 | } 42 | 43 | 44 | 45 | .card { 46 | padding: 2em; 47 | } 48 | 49 | @media (prefers-color-scheme: light) { 50 | :root { 51 | color: #213547; 52 | background-color: #ffffff; 53 | } 54 | a:hover { 55 | color: #747bff; 56 | } 57 | button { 58 | background-color: #f9f9f9; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /mfe1/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mfe1", 3 | "version": "0.0.0", 4 | "private": true, 5 | "engines": { 6 | "node": ">=16.0.0" 7 | }, 8 | "scripts": { 9 | "dev": "vite", 10 | "ng": "ng", 11 | "start": "npm run dev", 12 | "build": "vite build", 13 | "watch": "vite build --watch", 14 | "test": "vitest", 15 | "postinstall": "vite optimize" 16 | }, 17 | "dependencies": { 18 | "@angular/animations": "^14.0.0", 19 | "@angular/common": "^14.0.0", 20 | "@angular/compiler": "^14.0.0", 21 | "@angular/core": "^14.0.0", 22 | "@angular/forms": "^14.0.0", 23 | "@angular/platform-browser": "^14.0.0", 24 | "@angular/platform-browser-dynamic": "^14.0.0", 25 | "@angular/router": "^14.0.0", 26 | "@softarc/native-federation": "^1.0.0", 27 | "@softarc/native-federation-runtime": "^1.0.0", 28 | "rxjs": "~7.5.6", 29 | "tslib": "^2.4.0", 30 | "zone.js": "~0.11.8" 31 | }, 32 | "devDependencies": { 33 | "@analogjs/vite-plugin-angular": "latest", 34 | "@angular-architects/native-federation": "^1.0.0-beta.1", 35 | "@angular-devkit/build-angular": "^14.0.3", 36 | "@angular/cli": "~14.0.3", 37 | "@angular/compiler-cli": "^14.0.0", 38 | "@gioboa/vite-module-federation": "^0.2.3", 39 | "@softarc/native-federation-esbuild": "^1.0.0", 40 | "jsdom": "^20.0.0", 41 | "typescript": "~4.7.4", 42 | "vite": "^3.0.9", 43 | "vitest": "^0.22.1" 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /shell/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "shell", 3 | "version": "0.0.0", 4 | "private": true, 5 | "engines": { 6 | "node": ">=16.0.0" 7 | }, 8 | "scripts": { 9 | "dev": "vite", 10 | "ng": "ng", 11 | "start": "npm run dev", 12 | "build": "vite build", 13 | "watch": "vite build --watch", 14 | "test": "vitest", 15 | "postinstall": "vite optimize" 16 | }, 17 | "dependencies": { 18 | "@angular-architects/native-federation": "^1.0.0-beta.1", 19 | "@angular/animations": "^14.0.0", 20 | "@angular/common": "^14.0.0", 21 | "@angular/compiler": "^14.0.0", 22 | "@angular/core": "^14.0.0", 23 | "@angular/forms": "^14.0.0", 24 | "@angular/platform-browser": "^14.0.0", 25 | "@angular/platform-browser-dynamic": "^14.0.0", 26 | "@angular/router": "^14.0.0", 27 | "@softarc/native-federation": "^1.0.0", 28 | "@softarc/native-federation-esbuild": "^1.0.0", 29 | "@softarc/native-federation-runtime": "^1.0.0", 30 | "rxjs": "~7.5.6", 31 | "tslib": "^2.4.0", 32 | "zone.js": "~0.11.8" 33 | }, 34 | "devDependencies": { 35 | "@analogjs/vite-plugin-angular": "latest", 36 | "@angular-devkit/build-angular": "^14.0.3", 37 | "@angular/cli": "~14.0.3", 38 | "@angular/compiler-cli": "^14.0.0", 39 | "@gioboa/vite-module-federation": "^0.2.3", 40 | "jsdom": "^20.0.0", 41 | "typescript": "~4.7.4", 42 | "vite": "^3.0.9", 43 | "vitest": "^0.22.1" 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /mfe1/src/assets/vite.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /shell/src/assets/vite.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /mfe1/vite.config.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | import { defineConfig } from 'vite'; 4 | import angular from '@analogjs/vite-plugin-angular'; 5 | import { federation } from '@gioboa/vite-module-federation'; 6 | import { AngularEsBuildAdapter } from '@angular-architects/native-federation/src/utils/angular-esbuild-adapter'; 7 | 8 | // https://vitejs.dev/config/ 9 | export default defineConfig(({ mode, command }) => ({ 10 | root: 'src', 11 | publicDir: 'assets', 12 | server: { 13 | port: 3001, 14 | open: true, 15 | fs: { 16 | // Allowing access to both, project 17 | // and shared folder in dev mode 18 | allow: [ 19 | '.', 20 | '../../shared' 21 | ] 22 | } 23 | }, 24 | preview: { 25 | port: 3001, 26 | open: true, 27 | }, 28 | build: { 29 | outDir: `../dist/my-app`, 30 | emptyOutDir: true, 31 | target: 'es2020', 32 | }, 33 | resolve: { 34 | mainFields: ['module'], 35 | }, 36 | plugins: [ 37 | federation({ 38 | options: { 39 | workspaceRoot: __dirname, 40 | outputPath: 'dist/my-app', 41 | tsConfig: 'tsconfig.app.json', 42 | federationConfig: 'federation.config.cjs', 43 | verbose: false, 44 | dev: command === 'serve', 45 | }, 46 | adapter: AngularEsBuildAdapter, 47 | }), 48 | angular() 49 | ], 50 | test: { 51 | globals: true, 52 | environment: 'jsdom', 53 | setupFiles: ['test.ts'], 54 | include: ['**/*.spec.ts'], 55 | cache: { 56 | dir: `../node_modules/.vitest`, 57 | }, 58 | }, 59 | define: { 60 | 'import.meta.vitest': mode !== 'production', 61 | }, 62 | })); 63 | -------------------------------------------------------------------------------- /shell/vite.config.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | import { defineConfig } from 'vite'; 4 | import angular from '@analogjs/vite-plugin-angular'; 5 | import { federation } from '@gioboa/vite-module-federation'; 6 | import { AngularEsBuildAdapter } from '@angular-architects/native-federation/src/utils/angular-esbuild-adapter'; 7 | 8 | 9 | // https://vitejs.dev/config/ 10 | export default defineConfig(({ mode, command }) => ({ 11 | root: 'src', 12 | publicDir: 'assets', 13 | server: { 14 | port: 3000, 15 | open: true, 16 | fs: { 17 | // Allowing access to both, project 18 | // and shared folder in dev mode 19 | allow: [ 20 | '.', 21 | '../../shared' 22 | ] 23 | } 24 | }, 25 | preview: { 26 | port: 3000, 27 | open: true, 28 | }, 29 | build: { 30 | outDir: `../dist/my-app`, 31 | emptyOutDir: true, 32 | target: 'es2020', 33 | }, 34 | resolve: { 35 | mainFields: ['module'], 36 | }, 37 | plugins: [ 38 | federation({ 39 | options: { 40 | workspaceRoot: __dirname, 41 | outputPath: 'dist/my-app', 42 | tsConfig: 'tsconfig.app.json', 43 | federationConfig: 'federation.config.cjs', 44 | verbose: false, 45 | dev: command === 'serve', 46 | }, 47 | adapter: AngularEsBuildAdapter, 48 | }), 49 | angular(), 50 | ], 51 | test: { 52 | globals: true, 53 | environment: 'jsdom', 54 | setupFiles: ['test.ts'], 55 | include: ['**/*.spec.ts'], 56 | cache: { 57 | dir: `../node_modules/.vitest`, 58 | }, 59 | }, 60 | define: { 61 | 'import.meta.vitest': mode !== 'production', 62 | }, 63 | })); 64 | -------------------------------------------------------------------------------- /mfe1/src/polyfills.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This file includes polyfills needed by Angular and is loaded before the app. 3 | * You can add your own extra polyfills to this file. 4 | * 5 | * This file is divided into 2 sections: 6 | * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers. 7 | * 2. Application imports. Files imported after ZoneJS that should be loaded before your main 8 | * file. 9 | * 10 | * The current setup is for so-called "evergreen" browsers; the last versions of browsers that 11 | * automatically update themselves. This includes recent versions of Safari, Chrome (including 12 | * Opera), Edge on the desktop, and iOS and Chrome on mobile. 13 | * 14 | * Learn more in https://angular.io/guide/browser-support 15 | */ 16 | 17 | /*************************************************************************************************** 18 | * BROWSER POLYFILLS 19 | */ 20 | 21 | /** 22 | * By default, zone.js will patch all possible macroTask and DomEvents 23 | * user can disable parts of macroTask/DomEvents patch by setting following flags 24 | * because those flags need to be set before `zone.js` being loaded, and webpack 25 | * will put import in the top of bundle, so user need to create a separate file 26 | * in this directory (for example: zone-flags.ts), and put the following flags 27 | * into that file, and then add the following code before importing zone.js. 28 | * import './zone-flags'; 29 | * 30 | * The flags allowed in zone-flags.ts are listed here. 31 | * 32 | * The following flags will work for all browsers. 33 | * 34 | * (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame 35 | * (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick 36 | * (window as any).__zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames 37 | * 38 | * in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js 39 | * with the following flag, it will bypass `zone.js` patch for IE/Edge 40 | * 41 | * (window as any).__Zone_enable_cross_context_check = true; 42 | * 43 | */ 44 | 45 | /*************************************************************************************************** 46 | * Zone JS is required by default for Angular itself. 47 | */ 48 | import 'zone.js'; // Included with Angular CLI. 49 | 50 | 51 | /*************************************************************************************************** 52 | * APPLICATION IMPORTS 53 | */ 54 | -------------------------------------------------------------------------------- /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 recent versions of Safari, Chrome (including 12 | * Opera), Edge on the desktop, and iOS and Chrome on mobile. 13 | * 14 | * Learn more in https://angular.io/guide/browser-support 15 | */ 16 | 17 | /*************************************************************************************************** 18 | * BROWSER POLYFILLS 19 | */ 20 | 21 | /** 22 | * By default, zone.js will patch all possible macroTask and DomEvents 23 | * user can disable parts of macroTask/DomEvents patch by setting following flags 24 | * because those flags need to be set before `zone.js` being loaded, and webpack 25 | * will put import in the top of bundle, so user need to create a separate file 26 | * in this directory (for example: zone-flags.ts), and put the following flags 27 | * into that file, and then add the following code before importing zone.js. 28 | * import './zone-flags'; 29 | * 30 | * The flags allowed in zone-flags.ts are listed here. 31 | * 32 | * The following flags will work for all browsers. 33 | * 34 | * (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame 35 | * (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick 36 | * (window as any).__zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames 37 | * 38 | * in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js 39 | * with the following flag, it will bypass `zone.js` patch for IE/Edge 40 | * 41 | * (window as any).__Zone_enable_cross_context_check = true; 42 | * 43 | */ 44 | 45 | /*************************************************************************************************** 46 | * Zone JS is required by default for Angular itself. 47 | */ 48 | import 'zone.js'; // Included with Angular CLI. 49 | 50 | 51 | /*************************************************************************************************** 52 | * APPLICATION IMPORTS 53 | */ 54 | -------------------------------------------------------------------------------- /mfe1/src/assets/analog.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /shell/src/assets/analog.svg: -------------------------------------------------------------------------------- 1 | --------------------------------------------------------------------------------