How to Use Assets Properly in Module Federated Nx Angular Applications for Both Production and Development

Erman Enginler
HAVELSAN
Published in
5 min readJun 3, 2023

If you are using a module federated workspace at some point you will eventually encounter difficulties when serving assets from a remote application.

Created with Adobe Firefly

In this article I’m going to show you an approach on how to use assets properly in your remote applications. I will use Angular application in an Nx Workspace.

At the time I wrote this article I use:
node v16.20.0
npm v8.19.4
nx@16.1.4
angular@16.0.0

Assume you have a host and a remote application which are served at localhost:4200and localhost:4201respectively. When you want to use an asset -let’s say sample.png- in a remote application you put the sample.png physically at the assets folder in the remote application and call it like:
<img src='assets/sample.png' /> in your .html file.

sample.png used in remote application

This makes sense right? You put the sample.png which is related to remote1 application in remote1/src/assets folder and call it with the path src=assets/sample.png

When you start your workspace and navigate to remote1 application via localhost:4201 everything seems fine.

sample.png served through localhost:4201

But when you navigate to remote1 from host application at and check remote application which is rendered inside <router-outlet></router-outlet> you immediately notice that sample.png is not found.

Remote1 is rendered in host application after routing

The reason that sample.png is not found is: The browsers calls sample.png from localhost:4200/assets/sample.png (not 4201) which is the port for the host application and actually there is no sample.png resides in host/src/assets folder thus can not be served through localhost:4200/assets.

The most used but not applicable approach to solve this.

The most used approach is to configure a glob input/output for assets inside project.json which actually copies remote/assets contents to host/assets at serve and build time in background. This works pretty good when developing.

But this is not a good solution when it comes to production.

Think that you deploy host application to a host-container and remote1 application to remote-container. Where do you put sample.png? With this approach you have to put sample.png in host/assets folder because it will be served through host-container/assets/sample.png

But this doesn’t look right because sample.png is related to remote1 application. Think that you have a separate production team which is assigned to develop remote1 application. They make some changes for remote1, add and remove some assets for remote1. And when they want to deploy remote1 application they have to also build & deploy host application because assets are now served from host. Which makes remote1 deployment is creating a dependency over host application’s deployment.

In real life this will create some problems:

  • Host may not be ready for deployment when you want to deploy remote1 application. You probably have more than one remote application which makes this situation more difficult.
  • Your host/assets folders become crowded with assets from all other remote applications. You have to scaffold folders if you want to separate them per application.
  • You cannot isolate remote1 application’s process (CI/CD, build, deployment, development…) from host application’s process.

So how do we solve this properly?

We are going to create a proxy configuration on host application which handles specific calls to remote application.

First create a file named proxy.conf.json at apps/host.

Then open project.json in apps/host and add "proxyConfig:"apps/host/proxy.conf.json" at the serve node.

Then open proxy.conf.json and add

{
"/assets/remote1":{
"target": "http://localhost:4201",
"secure": false
}
}

Now all localhost:4200/assets/remote1 calls are actually called from localhost:4201/assets/remote1

To use assets in remote1 application you have to modify a few things.

  • First create a folder named remote1 in remote1/src/assets and move all remote1 assets to there.
assets folder in remote1 application
  • Then update src paths<img src='assets/sample.png' /> to <img src='assets/remote1/sample.png' />

You are all set.

When you start workspace with npm start you see that sample.png is called from localhost:4200/assets/remote1 but with the proxy.config it is actually served through localhost:4201/assets/remote1 and rendered without a problem.

When you navigate to localhost:4201 from your browser. Again it is working without a problem. This time calls are not pass through proxy (proxy is only configured in host application) but there is actually a sample.png resides in localhost:4201/assets/remote1

sample.png served via localhost:4201/assets/remote1

Development is done. What about production?

For the production you have to set a proxy configuration in your production server because this proxy we create only works for local development server.

You have to redirect host-application/assets/remote1 calls to remote1-application/assets/remote1

You may configure proxy paths to your needs or use pathRewrite to change location for the responses but keep in mind that after changing proxy configuration modify paths properly for your assets in remote applications.

In this article we learn how to create a proxy configuration to use for assets in module federated nx applications.

You may download the sample project on github
ermaneng/medium-assets (github.com)

Best
ermaneng

--

--