Lazy loading Angular components from Non-Angular applications
Tags: angular, javascript, cms, webcomponents
Published: 2020-03-21 18:54:39

---
title: Lazy loading Angular components from Non-Angular applications
published: true
description: Are you strugging to lazy load Angular components into your CMS platform or any other Non-Angular project? Then this article is for you!
tags: angular, javascript, CMS, web components
cover_image: https://dev-to-uploads.s3.amazonaws.com/i/3y780td6o4pjddrj26e1.png
canonical_url: https://indepth.dev/lazy-loading-angular-components-from-non-angular-applications
---
Are you strugging to lazy load Angular components into your CMS platform or any other Non-Angular project? Then this article is for you!


# **Introduction**
I have been working with Adobe Experience Manager (AEM) for almost two years and most of the time I combined it with Angular as a frontend framework. One of my first tasks as an AEM developer was to find a good way to use Angular in conjunction with the CMS platform.

At the time, Angular 6 had just been released and one of its main new features was Angular Elements. Angular Elements allows to create Web Components from Angular components and reuse them in other applications using different technologies. Since Web Components are framework agnostic and self-bootstrapped they are great for dynamic sites with CMS platforms.

There are some articles you can read about Angular Elements:
- https://juristr.com/blog/2019/04/intro-to-angular-elements/
- https://www.softwarearchitekt.at/aktuelles/angular-elements-part-i/
- https://www.softwarearchitekt.at/aktuelles/your-options-for-building-angular-elements/


# **Building**
One of the good things of Web Components and custom elements is that you import some JS and CSS and you are ready to use them. With Angular you can `run ng build --prod` and import the generated bundle files in other applications to use your custom elements.

![Build](https://dev-to-uploads.s3.amazonaws.com/i/9w79dadyx31nsti3yclc.png)

Also you can use ngx-build-plus to build your custom elements. With this library you can get a single bundle file when building your project with Angular CLI.


# **The problem**
Despite there are use cases where it could be handy to have all the components bundled to a single or a few files -like design systems-, there are other cases where it is not ideal.

In my particular case I have an Angular project with about 20 -big- components that are included as custom elements in a dynamic site powered by Adobe Experience Manager. But, only one or two of those components are included in each page.

So, if only one of the components is used within a page I would be delivering **a lot** of unnecessary JavaScript to the browser.


# **Lazy loading**
Code splitting and lazy loading would help to tackle that problem. You can split your application into multiple NgModules accordingly.

In my case, I could split up my project by creating a separate NgModule for each of my components and one or more shared modules to share features across the whole project. Now I would only need to lazy load them in order to lazy load my components.

There are several options to lazy load components in Angular, for example:
- [ngx-lazy-el](https://github.com/juristr/ngx-lazy-el)
- [angular-extensions/elements](https://github.com/angular-extensions/elements)

**But, how to lazy load the components from Non-Angular applications?**


# **ngx-element**
With [ngx-element](https://github.com/brunob15/ngx-element) you can lazy load your Angular components from everywhere. That means from a CMS platform, a React application or just a plain HTML.

_Repo: [https://github.com/brunob15/ngx-element](https://github.com/brunob15/ngx-element)_

The library will define a custom element which you can pass a selector attribute to. That selector attribute determines what component you want to load. Also you can pass in attributes to your component by setting data-attributes to the custom element.

Credits: Thanks to Juri Strumpflohner for the inspiration with ngx-lazy-el!


# **Usage**
Let’s create a small Angular application to see ngx-element in action :) I am using Angular CLI v9.0.6. Choose SCSS as the css preprocessor.

```
$ ng new lazy-components --minimal
$ cd lazy-components
```

We can remove `app.component.ts` since we won’t need it and modify `app.module.ts` accordingly.

After doing that our `app.module.ts` file should look like this:

{% gist https://gist.github.com/brunob15/ec3b431940235dded3218cc0440fe8ff %}

Basically I removed the `AppComponent` and added the `ngDoBootstrap` method since we are not bootsrapping any component in the module.

**Now let’s create a Talk component together with its feature module.**

```
$ ng g module talk
$ ng g component talk
```

At the moment you should have the following folder structure:

![Folder structure with a feature module and a component](https://dev-to-uploads.s3.amazonaws.com/i/s13usksypvakbp1p6cqf.png)

And your `talk` files should look as follow:

{% gist https://gist.github.com/brunob15/569807148c2dd7b7433bb54eef1024ca %}
{% gist https://gist.github.com/brunob15/be0a86b0e17600abc5ccef63ac603f92 %}

Let’s change our `Talk` component to make it display some information about a talk in a conference and give it some styles.

Update the `talk.component.ts` file to the following:
{% gist https://gist.github.com/brunob15/8282f680fb553271cb4b21e8ee3da66a %}

And create the following `talk.component.html` and `talk.component.scss` files next to `talk.component.ts`:

{% gist https://gist.github.com/brunob15/fedda5224b5f3fb8c5f1c4a58a3ecdcd %}
{% gist https://gist.github.com/brunob15/c8c86aa418ede513c1c7e4738218dc78 %}


Until now we have created a component that (trust me) will look like this later:

![Talk component](https://dev-to-uploads.s3.amazonaws.com/i/j6y93s74wwghkryew6vx.png)

**So nothing strange until now, right? We have created a typical Angular application with an AppModule, a feature module and one component.**

Remember that our goal is to use this component in Non-Angular applications and be able to lazy load it. We need Angular Elements and ngx-element in order to do that, so let’s put them in action…


#### **Install angular elements**
Angular provides a schematic to install and set up Angular Elements in our project. It will add a polyfill but it does not support IE11. If you need IE11 don’t use this schematic and see [this article](https://www.softwarearchitekt.at/aktuelles/angular-elements-part-i) instead.

Install Angular Elements by running `ng add @angular/elements` in your terminal.

#### **Install ngx-element**
And install ngx-element by running `npm install ngx-element --save`

#### **Expose the Talk component for ngx-element**
In order to let ngx-element to access our component and create it on demand we need to make a couple of additions to our `talk.module.ts`.

First we need to add `TalkComponent` to the `entryComponents` array. And second we are going to add a `customElementComponent` property to the module in order to make the component’s class accessible to ngx-element.

Our `talk.module.ts` should be like this now:
{% gist https://gist.github.com/brunob15/071f249e867c5041e6958fe71b09e0f7 %}

Once we have done this we need to import and configure the `NgxElementModule` in our `AppModule` as follows:
{% gist https://gist.github.com/brunob15/4c368904d45a42d4b7f89bee5737d7fa %}



# **Let’s test our component! 🎉**
In order to test our component we are going to create some HTML where we can use it. Remember that we are not bootstrapping any Angular component and we are just adding custom elements to the DOM.

Replace the `index.html` file in the project with the following markup:
{% gist https://gist.github.com/brunob15/ebb0127634161be05df5264417157c08 %}

And replace the global `styles.scss` file with:

{% gist https://gist.github.com/brunob15/6cbab233d34a130690f05b426432931c %}

# **Run it! 🚀**

At this point, if you run `ng serve` in your terminal you should see our component in action:

![Talks](https://dev-to-uploads.s3.amazonaws.com/i/ll4y745vsm58umv3btal.png)

And you can see that our Talk Module is being lazy loaded as we expected.

![Lazy loaded bundle](https://dev-to-uploads.s3.amazonaws.com/i/t8qw8tw23fw5xbfn7gks.png)

# **Play with it**
Now you can open your DevTools in the Network tab and verify that our `TalkModule` is being lazy loaded.

Some things you can play with to see the powers of custom elements:
- Add a new talk to the DOM and see how it is self-bootstrapped.
- Change the `title`, `description` and `speaker` attributes from the DevTools.
- Remove the talk custom elements from `index.html` file and verify that the `TalkModule` is not loaded initially. Then add a talk element to the DOM on the fly from the DevTools and verify that the `TalkModule` is lazy loaded.


# **Conclusions**
With ngx-element we have built a component and leveraged all benefits of Angular framework, custom elements and lazy loading.

This library has changed the way I integrate _Angular_ and _Adobe Experience Manager_ for the better. I hope this can be useful for developers trying to use Angular as a frontend framework together with CMS platforms or any other Non-Angular projects.

Thank you for reading 🙂