manfredsteyer / module-federation-plugin-example

258 stars 177 forks source link

Use service from remote microfrontend in shell app. #12

Open w3k5 opened 3 years ago

w3k5 commented 3 years ago

Hey everybody! Don't judge for my english, please. I need a help, because cannot find solution on my question. I have two separate application, host and remote. It isn't monorepo, and I want use Services and Components from remote app in host app not as page in router. For example in host app was created TestModule, and in template of this module I want use component from remote. Is it possible? Or I should create monorepo and create some shared libs and declare it in tsconfig?

w3k5 commented 3 years ago

My repos host app: https://github.com/w3k5/host-app-test remote app: https://github.com/w3k5/remote-app-test

murli2308 commented 3 years ago

I would suggest using libraries for sharing components between applications. You can create publishable libraries that can be shared across applications. nx g @nrwl/angular:lib shared-components --buildable --publishable

echonok commented 3 years ago

I would suggest using libraries for sharing components between applications. You can create publishable libraries that can be shared across applications. nx g @nrwl/angular:lib shared-components --buildable --publishable

Is it possible to share such a library, having two repos? For instanse, we have a repo with libraries and a repo with components. Components somehow must consume services from libraries. Is Module Federation a silver bullet for this case? Or we have to compile libraries and components in one monorepo?

dexster commented 2 years ago

Here's how I modified the example to work with a component not in the monorepo.

  1. After creating the auth-lib, build it - ng build auth-lib
  2. npm link the dist/auth-lib dir
  3. npm link auth-lib in the shell app and the remote component app
  4. Add the lib as a shared plugin in webpack.config in shell and remote - auth-lib": { singleton: true, strictVersion: true, requiredVersion: 'auto' }
  5. Add an entry to package.json in both shell and remote otherwise the created share above gives errors. In prod this would not be necessary as you would install the auth lib and not link it - auth-lib": "0.0.1
  6. Remove the @Injectable from the AuthService so that it is only instantiated once in the shell app. I also changed the user to an observable so that any updates to the username reflect immediately in federated modules. See AuthService code below
  7. Provide the AuthService in your app.module in the shell and remote - providers: [AuthService]
  8. Update your component and HTML to use the user$ property to view the user
import { BehaviorSubject } from "rxjs";

export class AuthService {

  private _user$ = new BehaviorSubject<string | null>(null);

  public get user$(): BehaviorSubject<string | null> {
      return this._user$;
  }

  public login(userName: string, password: string | null): void {
      this._user$.next(userName);
  }
}