angular-architects / module-federation-plugin

MIT License
730 stars 199 forks source link

Angular 14 MFE - Backward Compatibility #201

Open thutinavaneethreddy opened 2 years ago

thutinavaneethreddy commented 2 years ago

We have a microfrontend which is currently on angular 13. This microfrontend is being used in multiple shells apps (all of them currently on angular 13).

We are looking to upgrade the microfrontend app to angular 14 while making sure that it supports the angular 13 shell applications for a while until all shell applications move to angular 14.

We used scriptType: type/javascript to ensure backward compatibility as mentioned in the migration guides. But we are seeing issues in making this ng14 mfe work in ng13 shell app.

image

Is it possible to make an angular 13 shell application consume an mfe built with angular 14?

raphael22 commented 2 years ago

Same issue with v13 shell and v14 module. (Or v14 shell and v13 module)

pipe async/translate could not be found

remove async/translate pipe but then same as you:

NG0303: Can't bind to 'ngIf' since it isn't a known property of div

Try to remove singleton from @angular/common and others deps but this lead to more pitfall error (NG0203: inject()) I also try to set platformSharing: false in bootstrap but no more luck.

v14 shell with v14 module work fine though, but this means you have to update all your modules and re-deploy them along shell to make it work...but one of my goal with MF was to avoid this workflow.

Did we miss something @manfredsteyer ?

alirezabahary commented 2 years ago

Same issue with v13 shell and v14 module. (Or v14 shell and v13 module)

pipe async/translate could not be found

remove async/translate pipe but then same as you:

NG0303: Can't bind to 'ngIf' since it isn't a known property of div

Try to remove singleton from @angular/common and others deps but this lead to more pitfall error (NG0203: inject()) I also try to set platformSharing: false in bootstrap but no more luck.

v14 shell with v14 module work fine though, but this means you have to update all your modules and re-deploy them along shell to make it work...but one of my goal with MF was to avoid this workflow.

Did we miss something @manfredsteyer ?

i have same issue

alirezabahary commented 2 years ago

my shell project version is 13 and remote project version is 14 . pipe work in my remote project but when call remote project in my shell , I get an error:

core.mjs:6476 ERROR Error: Uncaught (in promise): Error: NG0302: The pipe 'date' could not be found in the 'RemoteComponent' component!. Find more at https://angular.io/errors/NG0302 Error: NG0302: The pipe 'date' could not be found in the 'RemoteComponent' component!. Find more at https://angular.io/errors/NG0302 at getPipeDef (core.mjs:22291:15) at Module.ɵɵpipe (core.mjs:22243:19) at RemoteComponent_Template (remote.component.html:3:1) at executeTemplate (core.mjs:9608:9) at renderView (core.mjs:9411:13) at renderComponent$1 (core.mjs:10692:5) at renderChildComponents (core.mjs:9276:9) at renderView (core.mjs:9436:13) at ComponentFactory.create (core.mjs:21588:13) at ViewContainerRef.createComponent (core.mjs:22832:47) at resolvePromise (zone.js:1213:1) at resolvePromise (zone.js:1167:1) at zone.js:1279:1 at ZoneDelegate.invokeTask (zone.js:406:1) at Object.onInvokeTask (core.mjs:25470:33) at ZoneDelegate.invokeTask (zone.js:405:1) at Zone.runTask (zone.js:178:1) at drainMicroTaskQueue (zone.js:582:1) card-board-micro-front-end.zip shell.zip

earbullet commented 2 years ago

I'm encountering a similar issue to this one and https://github.com/angular-architects/module-federation-plugin/issues/232

This occurs once the shell host is upgraded to ng 14 and the child MFE is still ng 13. I've tried the opposite of upgrading the child MFE and had a similar error. Pipes in the shell components (ng 14) all work but none of the child MFEs (ng 13) pipes work. It doesn't matter if the pipe is a custom pipe registered and declared in the module that is loaded or if it is a standard angular core pipe like uppercase.

An error has occured in the application Error: NG0302: The pipe 'uppercase' could not be found in the 'InitialComponent' component. Verify that it is declared or imported in this module.

The error occurs in this method below. In a working component the 'registry' variable has the appropriate pipes that exist in the view. In a non-working component the registry is null.

function getPipeDef(name, registry) {
    if (registry) { // registry = null
        for (let i = registry.length - 1; i >= 0; i--) {
            const pipeDef = registry[i];
            if (name === pipeDef.name) {
                return pipeDef;
            }
        }
    }
    if (ngDevMode) {
        throw new RuntimeError(-302 /* RuntimeErrorCode.PIPE_NOT_FOUND */, getPipeNotFoundErrorMessage(name));
    }
}
scottwalter-nice commented 2 years ago

Is your child app wrapped as a Webcomponent? That is how we handle different Angular versions between the container and child apps.

earbullet commented 2 years ago

I did not wrap the child apps in web components. As I understand the web component approach, each MFE would host it's own version of angular which could lead to more overhead as opposed to a single shared instance of angular. I'll get better performance long term not using web components but will have the compatibility issues I'm experiencing now. If that trade-off is incorrect I'm open to any insight. I will have a high number of dynamically added MFEs over time and not just a few static MFEs.

I was able to successfully run ng 13 on shell and ng 12 on all child MFEs. I had hoped I would be able to use the same approach to allow a rollout of each MFE as opposed to a one time switchover. 12 -> 13 allowed for a delayed rollout.

It is only the pipes that are not working so far going to 14 and I believe the module in ng 14 is not loading the pipes into a registry that ng 13 can consume or 14 is unable to see how the pipes are declared in the packed module. I'm at the point where I am digging into the angular module code to see how it loads the pipes. If I can resolve this issue I believe I can have a slightly offset rollout again to get all MFEs to 14.

raphael22 commented 2 years ago

Any news on this ?

raphael22 commented 1 year ago

Hi @manfredsteyer ! Is angular 15 might help to solve this ?

earbullet commented 1 year ago

I plan to test angular 15 in a couple weeks so I won't have any news from my approach until then.

raphael22 commented 1 year ago

@earbullet did you use "appType" with mfe bootstrap ?

earbullet commented 1 year ago

@raphael22 I am not using the webcomponent wrapper. When I upgraded from ng12 to ng13 they were compatible and worked. I believe the change might have to do with how pipes are registered starting in ng14. Surprisingly everything still works between 13 and 15 except for pipes.

I think I might need to do some restructuring to use the webcomponents but I'm early in testing now.

raphael22 commented 1 year ago

@earbullet I don't use wrapper either. But the bootstrap method from mfe tools has a appType argument I didn't notice : @angular-architects/module-federation-tools - Helper for Angular I will try this week.

raphael22 commented 1 year ago

Hum...Looks like I'm stuck with "NG0203: inject() must be called from an injection context". Even when microfrontend fetch with its own angular version.

raphael22 commented 1 year ago

Bump @manfredsteyer @mikezks

mikezks commented 1 year ago

It is like @scottwalter-nice mentioned:

earbullet commented 1 year ago

My solution ended up being to use the webcomponent wrapper for different versions. So when there is a major angular version upgrade we bootstrap all the MFEs using the webcomponent wrapper. Once everything is upgraded we switch back to native.

I was unable to find another solution which is really what I expected.