模块联合共享服务

如何解决模块联合共享服务

我正在使用Angular 11和Webpack 5进行新项目。我的工作基于使用Angular CLI的Manfred Steyer的Module Federation Plugin Example回购。 我不知道如何在两个应用程序之间从共享的本地Angular库中共享单例服务。

我会尽力解释我的设置。.非常抱歉这将持续多长时间。

简化的文件结构

root
  package.json
  projects/
    shell/
      src/app/
        app.module.ts
        app.component.ts
      webpack.config.ts <-- partial config
    mfe1/
      src/app/
        app.module.ts
        app.component.ts
      webpack.config.ts <-- partial config
    shared/
      src/lib/
        global.service.ts
      package.json <-- package.json for lib

角度

两个app.component.ts文件都是相同的

import {GlobalService} from 'shared';

@Component({
  selector: 'app-root',templateUrl: './app.component.html'
})
export class AppComponent {
  constructor(shared: SharedService) {}
}

global.service.ts

import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root'
})
export class GlobalService {

  constructor() {
    console.log('constructed SharedService');
  }
}

Webpack

shell / webpack.config.ts

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

module.exports = {
  output: {
    publicPath: "http://localhost:5000/",uniqueName: "shell"
  },optimization: {
    // Only needed to bypass a temporary bug
    runtimeChunk: false
  },plugins: [
    new ModuleFederationPlugin({
      remotes: {
        'mfe1': "mfe1@http://localhost:3000/remoteEntry.js"
      },shared: ["@angular/core","@angular/common","@angular/router"]
    })
  ],};

mfe1 / webpack.config.ts

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

module.exports = {
  output: {
    publicPath: "http://localhost:3000/",uniqueName: "mfe1"
  },plugins: [
    new ModuleFederationPlugin({

      // For remotes (please adjust)
      name: "mfe1",library: {type: "var",name: "mfe1"},filename: "remoteEntry.js",exposes: {
        './Module': './projects/mfe1/src/app/app.module.ts',},};

共享库package.json

{
  "name": "shared","version": "0.0.1","main": "src/public-api.ts","peerDependencies": {
    "@angular/common": "^11.0.0-next.5","@angular/core": "^11.0.0-next.5"
  },"dependencies": {
    "tslib": "^2.0.0"
  }
}

此配置可以编译并运行,但是mfe1实例化一个新的GlobalService。我看到“构造的SharedService”已登录到应用程序加载中,然后在加载远程模块后再次登录。我尝试遵循ScriptedAlchemy的another example,但是我不知道如何使它起作用。它要么编译并运行并创建两个实例,要么无法编译,具体取决于我确定如何弄乱我的配置。

ScriptedAlchemy示例使我似乎需要在shared文件的webpack.config.ts库数组中引用共享库。这完全有道理,但我无法正常工作

shell/webpack.config.ts and mfe1/webpack.config.ts
  ...
  shared: ["@angular/core","@angular/router","shared"]

如果以这种方式引用本地库,则不可避免地会在构建过程中出现错误

Error: Module not found: Error: Can't resolve 'shared' in '/Path/to/module-federation-plugin-example/projects/shell/src/app'

我发布的示例已简化。希望不会太过分,但这是link to a repo来显示问题

解决方法

TL; DR

  • 确保共享服务的所有模块依赖项也已共享。
  • 确保在webpack.config.ts中正确配置了共享配置

我将注意到我的项目是使用Angular CLI的NX Monorepo。我目前正在使用Angular 11.0.0-next和Webpack 5,在撰写本文时,它们只能作为ng11的可选组件使用。

如果您在tsconfig中使用路径别名,则习惯于导入“ @ common / my-lib”之类的本地库,但是无法在webpack配置中按别名共享模块。此外,如果您使用的是NX,则从绝对或相对库路径导入时,棉绒会抱怨,因此Webpack所需的内容与nx / tslint所需的内容之间是没有联系的。

在我的项目中,我有一些类似以下的库别名

tsconfig.base.json
...
"paths": {
    "@common/facades": [
        "libs/common/facades/src/index.ts"
    ],"@common/data-access": [
        "libs/common/data-access/src/index.ts"
    ]
}

要使其在我的webpack配置中起作用。我们必须使用这些别名,但是要使用import选项告诉webpack在哪里找到库

apps/shell/webpack.config.js
...
plugins: [
    new ModuleFederationPlugin({
        remotes: {
            'dashboard': 'dashboard@http://localhost:8010/remoteEntry.js','reputation': 'reputation@http://localhost:8020/remoteEntry.js'
        },shared:         {
            "@angular/core": {
                "singleton": true
            },"@angular/common": {
                "singleton": true
            },"@angular/router": {
                "singleton": true
            },"@angular/material/icon": {
                "singleton": true
            },"@common/data-access": {
                "singleton": true,"import": "libs/common/data-access/src/index"
            },"@common/facades": {
                "singleton": true,"import": "libs/common/facades/src/index"
            },"rxjs": {
                "singleton": true
            },"ramda": {
                "singleton": true
            }
        }
    })
]

这解决了Webpack在编译时无法找到模块的问题。

第二个问题是我试图共享依赖于公共数据访问服务的公共外观。我不打算共享数据访问服务,因为它们是无状态的,但是这导致我的MFE实例化了新的单例。这必须是因为共享服务具有“未共享”的依赖性。共享我的数据访问层和外观层导致整个应用程序共享单例。

在这里,依赖的问题是最重要的,因为它很难调试。没有错误或任何东西-事情并没有像您期望的那样工作。您甚至可能没有意识到,一开始您有两个共享服务实例。因此,如果遇到此问题,请查看依赖项,并确保您共享所需的一切。这可能是在应用程序之间保持最小共享状态/依赖性的一种论据。

  • 有关@ angular / material / icon共享配置的快速说明。在我的应用程序中,我用每个应用程序需要的图标填充MatIconRegistry。我必须共享@ angular / material / icon才能在每个MFE中共享单例。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-