简体   繁体   English

如何在 Module Federation 的 Angular 中创建我的服务的单个实例?

[英]How can I create a single instance of my service in Angular, in Module Federation?

I have recreated the issue with the repo available here: https://github.com/module-federation/module-federation-examples/tree/master/angular13-microfrontends-lazy-components .我已经通过此处提供的回购重新创建了问题: https://github.com/module-federation/module-federation-examples/tree/master/angular13-microfrontends-lazy-components

The mdmf-shared-service isn't being used by default, so I attempted to use it but notice two seperate instances of the service getting created for mdmf-shell, and mdmf-profile.默认情况下不使用 mdmf-shared-service,因此我尝试使用它,但注意到为 mdmf-shell 和 mdmf-profile 创建了两个单独的服务实例。 I've confirmed this by logging the constructor call and some local class values.我已经通过记录构造函数调用和一些本地 class 值来确认这一点。 Constructor is called twice and neither of the values passed to the instance is known to the other app.构造函数被调用两次,传递给实例的值都不为另一个应用程序所知。 Here is the code I added - what am I doing wrong?这是我添加的代码 - 我做错了什么?

mdmf-shared.service.ts mdmf-shared.service.ts

import { Injectable } from '@angular/core';
import { MdmfSharedModule } from '../modules/mdmf-shared.module';

@Injectable({
  providedIn: MdmfSharedModule, // I've also tried providedIn: 'root' and 'platform' same result
})
export class MdmfSharedService {
  private count: number = 0;
  private word: string = '';
  constructor() {
    console.log(this.count++)
  }

  ping(word?: string) {
    console.log('pinging mdmf shared service')
    this.word = word;
    console.log('this is the word: ', word)
  }
}

mdmf-shared.module.ts mdmf-shared.module.ts

import { NgModule } from '@angular/core';
import { MdmfSharedComponent } from '../components/mdmf-shared.component';
import { CommonModule } from '@angular/common';

@NgModule({
  // declarations: [MdmfSharedComponent, ListUserComponent],
  declarations: [MdmfSharedComponent],
  imports: [CommonModule],
  // exports: [MdmfSharedComponent, ListUserComponent]
  exports: [MdmfSharedComponent],
})
export class MdmfSharedModule {}

app.module(mdmf-shell) app.module(mdmf-shell)

import { APP_INITIALIZER, NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { RouterModule } from '@angular/router';
import { ShellModule } from './shell/shell.module';
import { AppComponent } from './app.component';
import { APP_ROUTES } from './app.routes';
import { MicrofrontendService } from './microfrontends/microfrontend.service';
import { MdmfSharedModule } from 'projects/mdmf-shared/src/lib/modules/mdmf-shared.module';
import { NgxsModule } from '@ngxs/store';
import { UserState } from 'projects/mdmf-shared/src/lib/app-state/state/user.state';

export function initializeApp(mfService: MicrofrontendService): () => Promise<void> {
  return () => mfService.initialise();
}

@NgModule({
  declarations: [AppComponent],
  imports: [
    BrowserModule,
    RouterModule.forRoot(APP_ROUTES),
    NgxsModule.forRoot([UserState]),
    MdmfSharedModule,
  ],
  providers: [
    MicrofrontendService,
    {
      provide: APP_INITIALIZER,
      useFactory: initializeApp,
      multi: true,
      deps: [MicrofrontendService],
    }
  ],
  bootstrap: [AppComponent],
})
export class AppModule {}

app.component.ts(mdmf-shell) app.component.ts(mdmf-shell)

import { Component } from '@angular/core';
import { MdmfSharedService } from 'projects/mdmf-shared/src/public-api';
import { MicrofrontendService } from './microfrontends/microfrontend.service';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss'],
})
export class AppComponent {
  title = 'mdmf-shell';
  constructor(public mfService: MicrofrontendService, public mdmfSharedService: MdmfSharedService) {
    mdmfSharedService.ping() // first instance
  }
}

app.module.ts(mdmf-profile) no imports of mdmf-shared.module or service app.module.ts(mdmf-profile)没有导入 mdmf-shared.module 或服务

profile.component.ts(mdmf-profile) profile.component.ts(mdmf-profile)

import { Component, OnInit } from '@angular/core';
import { FormGroup, FormBuilder, Validators } from '@angular/forms';
import { Store } from '@ngxs/store';
import { AddUser } from 'projects/mdmf-shared/src/lib/app-state/actions/user.action';
import { User } from 'projects/mdmf-shared/src/lib/app-state/models/User';
import { MdmfSharedService } from 'projects/mdmf-shared/src/lib/services/mdmf-shared.service';

@Component({
  selector: 'app-profile',
  templateUrl: './profile.component.html',
  styleUrls: ['./profile.component.css'],
})
export class ProfileComponent implements OnInit {
  angForm: FormGroup;

  ngOnInit(): void {}

  constructor(private fb: FormBuilder, private store: Store, public mdmfSharedService: MdmfSharedService) {
    mdmfSharedService.ping() // second instance
    this.angForm = this.createForm();
  }

  /**
   * Initialize the form
   */
  createForm(): FormGroup {
    return this.fb.group({
      name: ['', Validators.required],
      email: ['', Validators.required],
    });
  }

  /**
   * Handle the add user when the 'Create User' button is clicked
   * @param name: user's name
   * @param email: user's email
   */
  addUser(name: string, email: string): void {
    this.store.dispatch(new AddUser({ name, email } as User));
  }

  /**
   * Get the users for unit testing purposes
   */
  getUsers(): User[] {
    return this.store.selectSnapshot<User[]>(state => state.users.users);
  }
}

webpack.config.js(mdmf-shell) webpack.config.js(mdmf-shell)

const webpack = require('webpack');
const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin');

module.exports = {
  output: {
    publicPath: 'http://localhost:4200/',
    uniqueName: 'shell',
    scriptType: 'text/javascript',
  },
  optimization: {
    runtimeChunk: false,
  },
  plugins: [
    new ModuleFederationPlugin({
      remotes: {
        profile: 'profile@http://localhost:4201/remoteEntry.js}',
      },
      shared: {
        '@angular/core': { eager: true, singleton: true },
        '@angular/common': { eager: true, singleton: true },
        '@angular/router': { eager: true, singleton: true },
        '@ngxs/store': { singleton: true, eager: true },
        'mdmf-shared': { singleton: true, eager: true },
      },
    }),
  ],
};

webpack.config.js(mdmf-profile) webpack.config.js(mdmf 配置文件)

const webpack = require('webpack');
const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin');

module.exports = {
  output: {
    publicPath: 'http://localhost:4201/',
    uniqueName: 'mdmfprofile',
    scriptType: 'text/javascript',
  },
  optimization: {
    runtimeChunk: false,
  },
  plugins: [
    new ModuleFederationPlugin({
      name: 'profile',
      library: { type: 'var', name: 'profile' },
      filename: 'remoteEntry.js',
      exposes: {
        ProfileModule: './projects/mdmf-profile/src/app/profile/profile.module.ts',
      },
      shared: {
        '@angular/core': { singleton: true, eager: true },
        '@angular/common': { singleton: true, eager: true },
        '@angular/router': { singleton: true, eager: true },
        '@ngxs/store': { singleton: true, eager: true },
        'mdmf-shared': { singleton: true, eager: true },
      },
    }),
  ],
};

I solved my own problem, the issue I was facing - was using yarn link instead of adding the lib to the compiler options in tsconfig.json我解决了我自己的问题,我面临的问题 - 使用yarn link而不是将 lib 添加到tsconfig.json中的编译器选项

My theory is that yarn link removes visibility of the lib (instead simulating involvement with symlinks) and therefore removes it from compilation and the configuration of webpack's shareAll functionality.我的理论是 yarn link 移除了 lib 的可见性(而不是模拟符号链接的参与),因此将其从编译和 webpack 的 shareAll 功能的配置中移除。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在Angular中创建服务的单个实例 - Create Single Instance of Service in Angular 如何在类中使用Angular创建服务实例(可注入) - How can I create an instance of a service (injectable) with Angular inside a class 在 Angular 模块联合中,如何公开/访问远程模块的应用程序组件? - In Angular module federation, how do I expose/access the application component of my remote module? 如何在微前端中的 2 个应用程序与 webpack 模块联合(角度)之间建立关系 - how can I relation between 2 app in micro frontend with webpack module federation (angular) Angular azure 应用服务上的模块联盟 - Angular module federation on azure app service 我可以为 Angular 中的每个加载的组件创建一个服务实例吗? - Can I create an instance of a service for every loaded component in Angular? 在我的角度应用程序中创建服务的双重实例 - Create a double instance of a service in my angular app Angular 2中服务的单个实例 - Single instance of a service in Angular 2 angular2模块/应用程序中服务类的单个实例 - Single instance of a service class in angular2 Module / app 如何在Angular中动态创建服务? - How can I dynamically create a service in Angular?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM