DEV Community

Cover image for Lazy loading Angular components from Non-Angular applications
Bruno Bradach
Bruno Bradach

Posted on • Edited on • Originally published at 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:

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

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:

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

ngx-element

With 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

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:

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

And your talk files should look as follow:

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:

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


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

Talk component

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 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:

Once we have done this we need to import and configure the NgxElementModule in our AppModule as follows:

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:

And replace the global styles.scss file with:

Run it! 🚀

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

Talks

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

Lazy loaded bundle

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 🙂

Top comments (0)