Micro frontends with Aurelia

I’m planning on creating a large application with multiple teams managing their own frontend components and back end microservice. The desire is to create a composite UI from independent microservices that serve their bundled components, so individual features can have their own release schedule without affecting the shell UI.

Desired structure:

  • Aurelia UI Shell Project - contains the aurelia bootstrapper, AppRouter
  • Features
    • Microservice feature 1
      • UI - contains relevant aurelia UI components, may have one or more child routers
      • API
    • Microservice feature 2
      • UI - contains relevant aurelia UI components, may have one or more child routers
      • API
    • Microservice feature 3
      • UI - contains relevant aurelia UI components, may have one or more child routers
      • API

My question is, how would you split the microservice feature’s Aurelia components into separate projects so they can have their own release pipeline, whilst preventing duplication of common/shared libraries?

I’ve watched Jonathan Mezach’s presentation on a modular Aurelia frontend, but the examples shown are still maintaining components/bundles in a single project. https://www.youtube.com/watch?v=rODcaKW8uzY

3 Likes

Dreaming of the same concept.
sideloading compiled features.
Might wanna join our efforts.
Easy enough with jspm without bundling… i guess. If you are sure you can use http2, I’d start that way.

With webpack you also can move features to different bundles which will only be loaded if used.

@MaximBalaganskiy I could not yet figure out how could one build some feature with webpack separately and reference it on demand.

Heres an interesting approach using docker containers with a zero configuration proxy: https://github.com/willmendesneto/micro-frontend-pages

I started working on a solution using some of these concepts, where I would serve different bundles from each project in a different container, and use webpack and aurelia’s PAL to chunk my bundles.

With this setup, I haven’t conceptualized how I would be able to share a singleton instance across multiple apps, any ideas?

@Alexander-Taran I think you can bundle a feature and chunk the most of its’ content, leaving just a root module. Then in the consumer app reference a placeholder bundle in index.html which will load the main feature chunk on demand

Hi. I have just started looking at using Aurelia and how it can be used with a micro front end architecture.

I know its been a while, but any hints tips sample code you can point me in the direction off it would be much appreciated!

2 Likes

I think what you’re looking for is webpacks module federation Module Federation | webpack

I havent played with it yet but there are several samples, even a vanilla one. So with that said I guess its a matter of lazy init of Aurelia when a new module is requested where the enhance api might come in handy

1 Like

I’ve created a small repo for doing module federation with Aurelia here GitHub - bigopon/example-au-module-federation

Steps:

  1. build app 2
  2. build app 1
  3. run a webserver at dist folder of app 2 at port 8080
  4. run a webserver at dist folder of app 1 at any port

Start testing app 1 that is able to load app 2 modules like its own using Module Federation feature of webpack.

4 Likes

I got fired up by @bigopon’s shot at v1 and would like to share an Aurelia v2 example.

Including the same remote function call but also a remote custom element auto-wired in the router :wink:

5 Likes

I have this small example working fine. However, when attempting to get this integrated into a large complicated app we want to start breaking up, I’m running into challenges.

The large app is loading the remoteEntry.js file just fine, but when that file tries to load the real “superFunction_ts” chunk it’s failing because we use [contenthash] in the naming. It’s using “undefined” in place of the contenthash string. I updated the example app to prove that it will load files with contenthash just fine, and it does. What I noticed is that in the example app1, the line with import(“app2/superFunction”) gets updated to webpack_require.e(…) when built. Our monolith we are working on breaking up has left the import(…) statement after build. Maybe not an issue, but when stepping into the generated remoteEntry.js file, it seems it’s just webpack from the local scope instead of the remote scope.

I know this is vague at best, but I don’t have a project I can easily share to reproduce this behavior. I was hoping someone might have experienced something similar and found a solution. Basically, import() is loading the generated remoteEntry.js file, but when the code in remoteEntry.js tries to load the superFunction bundle, it’s failing because it’s not able to determine what the proper contenthash portion of the name should be. This feels like it happening because webpack is searching the host apps configurations for this value instead of the remote apps configuration.

i fear that without a repro this is going to be impossible to solve

Yeah, it’s ok. Likely not something we’ll be able to do. That being said, has anyone gotten Module Federation working with Aurelia 1 and actually using Components instead of simple methods that just print out to the console? I have taken the example above from @bigopon and exposed the App component from app2, but just can’t figure out how to actually use it in app1.

@zewa666 , this would be similar to what you have done in your Aurelia 2 example, except that Aurelia 1 doesn’t have a “component” property on a route config, but instead just a moduleId. I’ve been playing with the compose element, but am stuck…

I must admit I never had such a scenario to lazy register components with v1. I guess thats the missing part afterwards the moduleId should be available. Perhaps @dwaynecharrington or @bigopon know more?

anyways, this clearly shows one of the great improvements of v2 with super simple lazy loading with imports and the component router

Agreed, AU2 is going to be a really great framework when it’s ready for production. Unfortunately, I’m not seeing an easy upgrade path. But I’m excited to see how it evolves and look forward to migrating if/when that is possible for us.