Micro-frontends with Angular Web Components
cd angular
npm i
npm run build:web-components
cd ../vanilla
open index.html
I decided to name application angular, so
ng new angular
cd angular
-
Created alert component
-
Created alert service
-
I used @angular/material to create components with schematics:
-
navigation
defining input and output
angular/src/app/navigation/navigation.component.ts
export class NavigationComponent { @Input() sidebarTitle = 'Menu'; @Input() toolbarTitle = 'App'; @Output() linkSelected = new EventEmitter<number>(); ... }
I have created example layout inside
angular/src/app/app.component.html
, so to check how it works insure that it is bootstrapped:angular/src/app/app.module.ts
@NgModule({ ... bootstrap: [AppComponent], ... })
-
3. Add @angular/elements
ng add @angular/elements
Configuring:
import { createCustomElement } from '@angular/elements';
import { AppComponent } from './app.component';
@NgModule({
declarations: [AppComponent],
imports: [],
providers: [],
// clear bootstrap array before build!
bootstrap: [],
})
export class AppModule {
constructor(private injector: Injector) {}
ngDoBootstrap() {
// use @angular/elements function to create custom element
const customComponent = createCustomElement(AppComponent, {
injector: this.injector,
});
// define custom element with browser api in kebab-case (important, 2+ words)
customElements.define('ng-custom-component', customComponent);
}
}
4. Add ngx-build-plus
ng add ngx-build-plus
- Add new scripts to your package.json
package.json
"scripts": {
/*...*/
"build:prod:no-hashes": "ng build --prod --output-hashing none --single-bundle true",
"build:package-bundle": "cat dist/angular/{polyfills,main}.js > dist/angular/bundle.js",
"build:web-components": "npm run build:prod:no-hashes && npm run build:package-bundle",
"build:web-components:serve": "npm run build:prod:no-hashes && serve -l 5001 dist/angular"
}
Run build:web-components
script to build project and generate angular/dist/angular/bundle.js
5. Because I use material, I must cut all links with stylesheet from angular/src/index.html
and paste it to styles file
styles.css
@import url('https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500&display=swap');
@import url('https://fonts.googleapis.com/icon?family=Material+Icons');
@import url('https://fonts.gstatic.com');
Import /angular/dist/angular/bundle.js
into your second application. After building, your /angular/dist/angular/styles.css
might be empty, so skip it, if not, you must import also import it
Please look into your built angular html file to check what you also need to import to your vanilla project or to your angular styles file
There are 2 ways to connect angular bundle into your app:
1. By importing url into script file while serving angular builded project (not my way):
cd angular
npm run build:web-components:serve
Then copy all script imports from angular/dist/angular/index.html
(there are more then two) inside your vanilla file:
<script src="polyfills.js"></script>
<script src="main.js"></script>
THEN ADD http://localhost:5001/ TO SCRIPT FILES:
<script src="http://localhost:5001/polyfills.js"></script>
<script src="http://localhost:5001/main.js"></script>
Also import all styles
<script src="http://localhost:5001/styles.css"></script>
2. By importing builded bundle .js file
What I did inside vanilla html:
- Add css angular build
<head>
...
<link rel="stylesheet" href="../angular/dist/angular/styles.css" />
</head>
- Connect builded angular
.js
file into top of the body
<body>
<script src="../angular/dist/angular/bundle.js"></script>
...
</body>
- Add custom elements to html
<ng-alert></ng-alert>
- Bind input prop in
kebab-case
<ng-navigation toolbar-title="Vanilla Toolbar"></ng-navigation>
- Add event listener to output prop inside script tag | file
const nav = document.querySelector('ng-navigation');
nav.addEventListener('linkSelected', alert);