[英]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.