I am currently trying out Angular Elements for creating web components. I have created a web component that works in an html page:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Test</title>
</head>
<body>
<nav-bar title="Test"></nav-bar>
<script type="text/javascript"
src="https://dev-week-web-components.s3.eu-central-1.amazonaws.com/nav-bar.js"></script>
</body>
</html>
The web component is displayed correctly and the title attribute is set.
As soon as I embed the web component in an Angular app, the app root component no longer works. The app root component is always empty, even though it has content! If I remove the script tag for loading my web component, the app root component of the shell project works again.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>NgElementsShell</title>
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
<script type="text/javascript"
src="https://dev-week-web-components.s3.eu-central-1.amazonaws.com/nav-bar.js"></script>
</head>
<body>
<nav-bar></nav-bar>
<app-root></app-root> <!-- Always empty! -->
</body>
</html>
To create the web component I followed this tutorial: https://medium.com/comsystoreply/angular-elements-569025b65c69 (german only).
The web component created with Angular Elements is the app component of another Angular project.
@NgModule({
declarations: [AppComponent],
imports: [
BrowserModule,
NgbModule,
],
entryComponents: [AppComponent]
})
export class AppModule {
constructor(private injector: Injector) {
}
ngDoBootstrap() {
if (!customElements.get('nav-bar')) {
const navBarElement = createCustomElement(AppComponent, {injector: this.injector});
customElements.define('nav-bar', navBarElement);
}
}
}
The Angular project for the web component contains only this one component:
@Component({
// tslint:disable-next-line:component-selector
selector: 'nav-bar',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss'],
encapsulation: ViewEncapsulation.ShadowDom
})
export class AppComponent implements OnInit {
@Input() title = 'Web-Component';
constructor() { }
ngOnInit(): void {
}
}
The nav-bar.js file is a concated file of main.js, polyfill.js runtime.js and vendor.js from the built Angular application. In the tutorials, a scripts.js file is used. I do not have this file. If I leave out the vendor.js file, the web component does not work.
What am I doing wrong?
Thanks to user14649759's tip, I was able to solve the problem! :)
Webpack 5 must be used. To achieve this, I have made the following changes:
npm install -g yarn@latest
yarn add webpack@latest
yarn add copy-webpack-plugin@latest
Add to package.json:
"resolutions": {
"webpack": "^5.31.0"
},
Tell Angular to use yarn:
ng config cli.packageManager yarn
The use of yarn is necessary because yarn uses the resolutions
specification.
Sources: