I created a demo app using the @angular/elements
package (v19) to build an mfe-1
app as a web component, which is then displayed inside another app called shell
. Both apps are set up with the Angular application builder and are housed within an Nx monorepo to streamline the workflow.
Here’s an overview of my setup:
1- App mfe-1
:
For reference, the main.ts
file looks like this:
import { createCustomElement } from '@angular/elements';
import {
createApplication
} from '@angular/platform-browser';
import { AppComponent } from './app/app.component';
import { appConfig } from './app/app.config';
(async () => {
const appRef = await createApplication(appConfig);
const appComponent = createCustomElement(AppComponent, {
injector: appRef.injector,
});
customElements.define('nds-mfe-1', appComponent);
})();
everything else is standard to angular apps in the new standalone style.
i adjusted the build process to not hashing the build output, so that i can easily integrate the main.js
file in another app.
nds-mfe-1
element. Shell also doesnt have many content and simply have a placeholder from the generated app.i wrote a simple service to integrate the main.js
script as module into the page, so that i can render my element.
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root',
})
export class MicroFrontendLoaderService {
private loaded = false;
loadScript(url: string): Promise<void> {
return new Promise((resolve, reject) => {
if (this.loaded) {
resolve();
return;
}
const script = document.createElement('script');
script.src = url;
script.type = 'module';
script.onload = () => {
this.loaded = true;
resolve();
};
script.onerror = () => {
reject(new Error(`Failed to load script: ${url}`));
};
document.body.appendChild(script);
});
}
}
As soon as i call the script inside my component, the component is rendered twice. This make my main.js
appear twice in the DOM as script tag. My web components does not appear on the page.
Here is the full reproduction of my issue on github.. Just run npm install
and then nx serve shell
to start the setup.
Can someone explain why i get this behavior?
constructor runs twice as soon as i try to include the web component script
I've placed your script in the public
folder, which is a replacement for the assets folder in newer Angular versions. Also, I renamed the resulting main.js
file to custom-element.js
to avoid name collision.