The Problem

Trying to get 2 distinct Angular applications onto a single HTML page. When you try to do this, you’ll notice that your 2nd application will not render.

I know most of you Angular gurus out there are asking why anyone would want to do this. Angular is an enterprise framework meant for building SPA’s not individual widgets. I definitely agree that SPA design is where Angular shines but not all businesses are able to follow such a pattern, or are upgrading to a SPA and need to be able to build out individual widgets to replace existing legacy widgets until they can fully upgrade to a SPA.

So that being the case let’s take a look at what happens if you throw 2 apps on a single page:

Application 1 showing up because it is on top in the source

Application 2 showing up because it is on top in the source

As you can see that only one app renders (Whichever app’s scripts come first in the html). So how do we get around this.

Solution 1

One solution that you can find online to make this work is to simply wrap each of your Angular Applications in an iFrame. If you are like me and you see the solution is an iFrame, you probably shudder (don’t worry I will go over a nicer solution). This technically works, because each app is running in it’s own sandboxed environment and therefore does not cause issues with any other application. For simple apps this can work, but when things get more complicated and you need inputs in or out of your application then this can become more of an issue. Your application also does not have access to the routes on the parent windows, and ends up being a communication nightmare.

Solution 2

Use Angular Elements. If you have not used Angular Elements, they are a fantastic tool that allows you to compile Angular applications into Web Components. This allows for a more native JS/HTML approach. I will not go into how to create Angular Elements in this article, but there lots of great resources out there around that topic.

We used this approach for awhile and worked great… until it didn’t. The issue became upgrades. So while things would work great for awhile, if App 1 upgraded Angular or another dependency that the App 2 depended on and deployed before the other app upgrades (and there was a breaking change), then one or both of the apps would just stop working on the page. This is a big issue because it only occurs at run time and there is no way to know if one App has a breaking change until you throw both on a page. This made our upgrade processes very cumbersome and required coordinated releases which goes against our CI/CD processes and does not separate our concerns out well enough. So while a viable solution this was not the solution we were looking for.

Solution 3

This brought me to look for a new answer, something that would support the sandboxed approach of iFrames but not with the ability for the apps to live natively on the page like with Angular Elements. After digging for awhile, I was unable to find a solution to this problem. So why do these apps only show up with the top one is available. To figure this out, we have to dig into how Angular compiles our files. When we look under the hood, it is just using Webpack to create our bundles. Knowing this and digging in, I discovered the Webpack creates a single namespaced object on the window. To see this open your console on any page with an Angular App on it and type window.webpackJsonp . Once you see that you will see all the objects that webpack has namespaced underneath this object. This gave me the idea to try to rename the outputted namespace. Angular doesn’t give you the ability to do this natively, but luckily after playing with Angular Elements, I was able to play with the tool Ngx Build Plus. This is a very powerful tool that allows you to configure Webpack for your Angular build process.

This tool works for both Nrwl Nx and for an regular Angular application. In this tutorial, we will look at just implementing in an existing standalone Angular App.

To start run “npm install ngx-build-plus -D”

You can than add build plus as your projects builder by running “ng add ngx-build-plus”

We have now set up Angular’s builder to use ngx-build-plus, which means we just need to configure our build process.

To do this, we just need to add a file at our root level, we will call this webpack.extra.js. Once you have that created, you just need to add the following as it’s

module.exports = {

output: {

jsonpFunction: 'namespacedName'

}

}

Replace ‘namespacedName’ with your application’s unique namespaceName. For this example I used webpackApplicationOne and webpackApplicationTwo

Now we just need to run our build with one extra parameter “ng build — prod — extra-webpack-config webpack.extra.js”

Now when I combine my 2 apps into a single index.html and run it I get:

2 working apps on one page

We can see our app is now up and running! There are some disadvantageous and limitations with this approach. The first one is what you can do with the router (There are 2 apps fighting for the same routes). If you only have one routeable app, this shouldn’t be an issue. This also means that you are loading Angular and all shared dependencies twice. This can be a performance decrease, but with some tricks to load apps on scroll or after page load and with Ivy’s new tree shaking, hopefully you can get each smaller application down to a manageable easier to load time. Please feel free to comment and share your experiences with this.

Nick Favero is an Angular advocate who loves the environment it provides. He is a Senior Software Engineer at DHI Group/Dice, and if you are looking for a new Tech Career, find a new career at Dice.com or a job at DHI