├── .gitignore
├── README.md
├── demo
├── index.html
└── mfe_logo.png
├── package-lock.json
├── package.json
├── projects
├── first
│ ├── first.mfe.ts
│ ├── package.json
│ └── tsconfig.json
├── host
│ ├── host.mfe.ts
│ ├── package.json
│ └── tsconfig.json
├── second
│ ├── package.json
│ ├── second.mfe.ts
│ └── tsconfig.json
└── shared
│ ├── package.json
│ ├── shared.mfe.ts
│ └── tsconfig.json
└── tsconfig.json
/.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 | # Only exists if Bazel was run
8 | /bazel-out
9 |
10 | # dependencies
11 | /node_modules
12 |
13 | # profiling files
14 | chrome-profiler-events*.json
15 | speed-measure-plugin*.json
16 |
17 | # IDEs and editors
18 | /.idea
19 | .project
20 | .classpath
21 | .c9/
22 | *.launch
23 | .settings/
24 | *.sublime-workspace
25 |
26 | # IDE - VSCode
27 | .vscode/*
28 | !.vscode/settings.json
29 | !.vscode/tasks.json
30 | !.vscode/launch.json
31 | !.vscode/extensions.json
32 | .history/*
33 |
34 | # misc
35 | /.sass-cache
36 | /connect.lock
37 | /coverage
38 | /libpeerconnection.log
39 | npm-debug.log
40 | yarn-error.log
41 | testem.log
42 | /typings
43 |
44 | # System Files
45 | .DS_Store
46 | Thumbs.db
47 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | #  Angular Micro Frontends
2 |
3 | ## Pure Angular toolchain without 3rd party
4 |
5 | Example repository and boilerplate to build *__real micro frontends__* with angular.
6 |
7 | ### How this repository differs from the examples in the WWW?
8 |
9 | > Micro Frontends in its essence means being able to build, compile, load and use frontends that work **independently**.
10 | It **must be** possible to include micro frontends on runtime without configuration change.
11 | This also means that including a micro frontend **must not** involve recompilation
12 | >
13 | > Otherwise it is just lazy loading with some overhead.
14 | > But since we all live in a free world, everyone can call all the stuff however one wants to.
15 |
16 | Enjoy it. Or not. It's up to you.
17 |
18 | ## How does all this work?
19 |
20 | 1. We make use of the great [ng-packagr](https://github.com/ng-packagr/ng-packagr) package which kinda does all the job for us.
21 | 2. [Ng-packagr uses rollup under its hood](https://github.com/ng-packagr/ng-packagr/blob/master/src/lib/flatten/rollup.ts).
22 | This means by default, every dependency is excluded from the angular application we are building.
23 | 3. Ng-packagr outputs the application in FESM
24 | ([also ESM, which is basically used to create the other formats](https://github.com/ng-packagr/ng-packagr/blob/master/src/lib/ng-package/entry-point/write-bundles.transform.ts#L46))
25 | 4. We could make use of UMD, but it's deprecated, so we stick with ESM.
26 |
27 | A curcial step is to "link" the angular packages in fully compilation mode. (which is done in this repo as a postinstall step).
28 | It is also important to build your micro frontends with ivy. This is required, so a runtime compilation is not necessary anymore.
29 |
30 | Basically
31 |
32 | ```
33 | # Install packages
34 | npm ci
35 | # Run the live-server
36 | npm run serve
37 | # Build the shared library
38 | npm run shared
39 | # Build the host micro frontend
40 | npm run host
41 | ```
42 |
43 | So you just build the host application (sometimes called "shell")
44 |
45 | *Now comes the part where you see what these micro frontends are of
46 | and not like the examples you can find all over the WWW.*
47 |
48 |
49 | ```
50 | # Keep your browser with index.html open!
51 | # Build the first micro frontend
52 | npm run first
53 | ```
54 |
55 | Now type in your browser console
56 | ```js
57 | hostMfe.loadMfe("@angular-mfe/first");
58 | ```
59 | This will load the just compiled micro frontend bundle.
60 | **and creates an instance of it, on runtime!**
61 |
62 | You should see in the console following output
63 | ```html
64 | Registering MFE-ONE
65 | Total registered: 1
66 | ```
67 |
68 | ‼️ Without any reload / refresh of your browser page you just added features to your application ‼️
69 |
70 | And because people don't realize this small, but excellent possibility,
71 | another round.
72 |
73 | 1. Let's add again a feature to the **running** app.
74 | 2. Just **compile** the second MFE: `npm run second`
75 | 3. **Without reloading**, type in the console of the **running** app:
76 | ```js
77 | hostMfe.loadMfe("@angular-mfe/second");
78 | ```
79 | Which results the following output
80 | ```html
81 | Registering MFE-TWO
82 | Total registered: 2
83 | ```
84 |
85 | Take a break and think about it.
86 |
87 | ### Drawbacks
88 |
89 | This approach requires a bit more knowledge in [importmaps](https://github.com/WICG/import-maps) which landed in Chrome 89, but
90 | 1. The angular packages are published in partially compilation mode. For this approach the fully compilation is required. This is done by using `@babel/cli` together with the `@angular/compiler-cli/linker/babel` plugin
91 | 2. rxjs does not provide FESM formats and somehow bugs with the exports, so we make use of skypack (Thank you folks!)
92 | 3. ESM cannot be loaded from the filesystem, therefore we need to start a local webserver (e.g. live-server)
93 | 4. FESM2020 is not compatible out of the box with zone.js when using `async await`. Therefore FESM2015 bundles are used to avoid issues. Thanks @petebacondarwin for this [crucial information](https://github.com/angular/angular/issues/43716#issuecomment-934628526)
94 |
95 | Cheers
96 |
97 | flash :zap:
98 |
--------------------------------------------------------------------------------
/demo/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |