Introduction
What I will describe here is a way to have a mono-repo containing a main Angular app (host) and one or more Angular Elements based apps (childs). You will be able to use the elements in your main app by bundling all them together or you can pack your element with npm and import it as a npm dependency. This is heavily based on what is described by Manfred Steyer in his Angular Elements blog series so I advice you to read that to get some context and fill some missing pieces.
Be aware though, that currently the approach I describe here will not avoid duplicated dependencies across your multiple apps.
Solution
In your existing Angular project you can create a child application with ng generate application <name>
. See documentation for more details.
Turn your newly created project to an Angular Element.
To help you build your projects take a look at the Angular CLI extension ngx-build-plus
here. For my case I didn't apply most of the recipe described in the ngx-build-plus
docs as it is about sharing dependencies across projects which I will not detail here. All I needed was what follows.
The steps to build this architecture are roughly:
ng add ngx-build-plus
ng add ngx-build-plus --project <name>
- create npm scripts:
- for elements projects:
"build:client-a": "ng build --prod --project client-a --single-bundle true --output-hashing none --vendor-chunk false"
- for host app, regular build commands like
ng build
, ng serve
- add path to the generated elements JS file to the host app build configuration - you add it in scripts property in
angular.json
- add path to the custom elements polyfill JS file to the element apps build configuration - you add it in scripts property in
angular.json
. Each app has its own configuration and scripts entry.
After you build your elements project, its single file bundle will typically go to ./dist/<project-name>/
. You can create an npm package from that content and use it as a library.
Notes
Two ways to bundle the child apps with the host app. In the host app scripts configuration, you either add the path to the child apps in the dist/
folder or you add the path to the child apps in node-modules/
folder (when child apps are imported as npm packages).
Creating an Angular library instead of an Angular application for this purpose will not work because Angular libraries generated by the CLI cannot be used outside an Angular project - this was not very clear in the documentation.
Make sure that the component doesn't have dependencies to the parent app and you should be fine. I handled dependencies by converting them to component inputs or by doing content projection.
When you have a component A which includes a component B. You want to turn component A into an angular element but component B is used in several parts of your application. If you don't want to maintain two copies, one in the application and other in your component A library, it might be a good case to take advantage of content projection (aka Web Component slots).
Be aware that I haven't done this in production and its not what you would call a stable architecture.