2

Lets assume that I'll use nx to be able to share libraries between different sites in a mono repo. I have two sites:

  • Site 1: Angular App
  • Site 2: Static Site

Site 1 has a helloWorld Angular Component. On site 2 I want to use the helloWorld component, but as a web component created by an Angular Element. All the Angular Components and Elements should be stored in a shared, external nx library.

Is there a way to share code between the regular Angular Component and the Angular Element? Or, nest the regular component inside the element?

edt
  • 22,010
  • 30
  • 83
  • 118
  • maybe you can add more details about what kinds of data are you hoping to share between the 2? are these 2 components on the same server and contained in the same angular project? – Rick Feb 23 '21 at 00:21
  • Thanks @Rick. There is no data shared between the 2. The helloWorld component simply outputs "Hello World!". There is no Angular app for site 2. It should use only Angular Elements. – edt Feb 23 '21 at 00:31
  • You could try to convert the common shared components into their own library, the Elements and the regular angular app could then both import what they needed from there. – Mikkel Christensen Mar 01 '21 at 02:11

2 Answers2

6

There is a possible solution in a few steps.

1. Generate a library

The first step is to generate nx library where you want to store shared custom elements.
nx g lib custom-elements

Add build step for this library in angular.json with something like:

        "build": {
          "builder": "@angular-devkit/build-angular:browser",
          "options": {
            "outputPath": "dist/libs/custom-elements",
            "index": "libs/custom-elements/src/lib/index.html",
            "main": "libs/custom-elements/src/lib/main.ts",
            "tsConfig": "libs/custom-elements/tsconfig.lib.json",
            "aot": true,
            "assets": [],
            "styles": [],
            "scripts": []
          },
          "configurations": {
            "production": {
              "fileReplacements": [],
              "optimization": true,
              "outputHashing": "none",
              "sourceMap": false,
              "namedChunks": false,
              "extractLicenses": true,
              "vendorChunk": false,
              "buildOptimizer": true,
              "budgets": [
                {
                  "type": "initial",
                  "maximumWarning": "2mb",
                  "maximumError": "5mb"
                },
                {
                  "type": "anyComponentStyle",
                  "maximumWarning": "6kb",
                  "maximumError": "10kb"
                }
              ]
            }
          }
        },

The main part there is "builder": "@angular-devkit/build-angular:browser",, because we will use files built by this library later. Also don't forget to add empty index.html file.

2. Mark your angular components as custom elements

Firstly, add angular elements npm install @angular/elements.
Then mark the components you want to share using createCustomElement:


@NgModule({
   imports: [BrowserModule],
   entryComponents: [SomeComponent],
})
export class SharedComponentsModule {
   constructor(readonly injector: Injector) {
       const ngElement = createCustomElement(SomeComponent, {
           injector,
       });

       customElements.define('some-component', ngElement);
   }

   ngDoBootstrap() {}
}

3. Build the library and add necessary scripts to your static page

Run nx build custom-elements. You will get all the files in dist/libs/custom-elements. You are now able to add them to any page and use custom elements!

Working example

I created a working example here https://github.com/nickbullock/share-custom-elements-between-angular-and-static-app

How to run angular app: npm start
How to run static app: npm run app2:serve

Additional read

https://indepth.dev/posts/1116/angular-web-components-a-complete-guide

https://medium.com/angular-in-depth/how-to-compile-your-angular-components-library-into-web-components-47ff0ac73bd7

nickbullock
  • 6,424
  • 9
  • 27
1

Is there a way to share code between the regular Angular Component and the Angular Element?

Yes, This is why we use libraries. Libraries are not just a way to share code in Nx. They are also useful for factoring out code into small units with a well-defined public API. The NX recommends having a small number of library types.

According to angular.io, Angular elements are Angular components packaged as custom elements (also called Web Components), so what you need is Nx Plugin for Web which contains generators for managing Web Component applications and libraries within an Nx workspace. You may need the helpful instructions inside Create Libs in Angular using NX to meet your purpose.

Is there a way to nest the regular component inside the element?

Yes, As Angular allows us to put reusable logic into the separate units.

Amirhossein Mehrvarzi
  • 18,024
  • 7
  • 45
  • 70